Skip to content

Commit

Permalink
Fixes fog#193 - boot_order update
Browse files Browse the repository at this point in the history
  • Loading branch information
ezr-ondrej committed Mar 23, 2019
1 parent 9fa156b commit b609505
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 25 deletions.
22 changes: 11 additions & 11 deletions lib/fog/vsphere/requests/compute/create_vm.rb
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ def boot_options(attributes, vm_cfg)
# e.g. Fog::Compute.new(provider: "vsphere", vsphere_rev: "5.5", etc)
options = {}
if (@vsphere_rev.to_f >= 5) && attributes[:boot_order]
options[:bootOrder] = boot_order(attributes, vm_cfg)
disks = vm_cfg[:deviceChange].map { |dev| dev[:device] }.select { |dev| dev.is_a? RbVmomi::VIM::VirtualDisk }
options[:bootOrder] = boot_order(attributes[:boot_order], attributes[:interfaces], disks)
end

# Set attributes[:boot_retry] to a delay in miliseconds to enable boot retries
Expand All @@ -126,39 +127,38 @@ def boot_options(attributes, vm_cfg)
options.empty? ? nil : RbVmomi::VIM::VirtualMachineBootOptions.new(options)
end

def boot_order(attributes, vm_cfg)
def boot_order(fog_boot_order, nics, disks)
# attributes[:boot_order] may be an array like this ['network', 'disk']
# stating, that we want to prefer network boots over disk boots
boot_order = []
attributes[:boot_order].each do |boot_device|
vm_boot_order = []
fog_boot_order.each do |boot_device|
case boot_device
when 'network'
if nics = attributes[:interfaces]
if nics
# key is based on 4000 + the interface index
# we allow booting from all network interfaces, the first interface has the highest priority
nics.each do |nic|
boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableEthernetDevice.new(
vm_boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableEthernetDevice.new(
deviceKey: 4000 + nics.index(nic)
)
end
end
when 'disk'
disks = vm_cfg[:deviceChange].map { |dev| dev[:device] }.select { |dev| dev.is_a? RbVmomi::VIM::VirtualDisk }
disks.each do |disk|
# we allow booting from all harddisks, the first disk has the highest priority
boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableDiskDevice.new(
vm_boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableDiskDevice.new(
deviceKey: disk.key
)
end
when 'cdrom'
boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableCdromDevice.new
vm_boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableCdromDevice.new
when 'floppy'
boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableFloppyDevice.new
vm_boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableFloppyDevice.new
else
raise "failed to create boot device because \"#{boot_device}\" is unknown"
end
end
boot_order
vm_boot_order
end

def create_nic_backing(nic, attributes)
Expand Down
32 changes: 26 additions & 6 deletions lib/fog/vsphere/requests/compute/update_vm.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,24 @@ def update_vm(server)
spec[:memoryMB] = attributes[:memory_mb]

# Volumes
device_change.concat(update_vm_volumes_specs(vm_mob_ref, server.volumes))
vm_volumes = vm_mob_ref.config.hardware.device.grep(RbVmomi::VIM::VirtualDisk)
device_change.concat(update_vm_volumes_specs(vm_volumes, server.volumes))

# Networks
device_change.concat(update_vm_interfaces_specs(vm_mob_ref, server.interfaces, datacenter))
vm_nics = vm_mob_ref.config.hardware.device.grep(RbVmomi::VIM::VirtualEthernetCard)
device_change.concat(update_vm_interfaces_specs(vm_nics, server.interfaces, datacenter))

spec[:deviceChange] = device_change unless device_change.empty?
if attributes.key?(:boot_order) || attributes.key?(:boot_retry)
spec[:bootOptions] = update_boot_options(attributes, vm_nics, vm_volumes)
end

vm_reconfig_hardware('instance_uuid' => attributes[:instance_uuid], 'hardware_spec' => spec) unless spec.empty?
end

private

def update_vm_interfaces_specs(vm_mob_ref, fog_interfaces, datacenter)
vm_nics = vm_mob_ref.config.hardware.device.grep(RbVmomi::VIM::VirtualEthernetCard)
def update_vm_interfaces_specs(vm_nics, fog_interfaces, datacenter)
modified_nics = fog_interfaces.to_a.take(vm_nics.size)
new_nics = fog_interfaces.to_a.drop(vm_nics.size)

Expand All @@ -61,8 +65,7 @@ def update_vm_interfaces_specs(vm_mob_ref, fog_interfaces, datacenter)
specs
end

def update_vm_volumes_specs(vm_mob_ref, volumes)
vm_volumes = vm_mob_ref.config.hardware.device.grep(RbVmomi::VIM::VirtualDisk)
def update_vm_volumes_specs(vm_volumes, volumes)
modified_volumes = volumes.to_a.take(vm_volumes.size)
new_volumes = volumes.to_a.drop(vm_volumes.size)

Expand All @@ -83,6 +86,23 @@ def update_vm_volumes_specs(vm_mob_ref, volumes)
specs
end

def update_boot_options(attributes, vm_nics, vm_volumes)
# NOTE: you must be using vsphere_rev 5.0 or greater to set boot_order
# e.g. Fog::Compute.new(provider: "vsphere", vsphere_rev: "5.5", etc)
options = {}
if (@vsphere_rev.to_f >= 5) && attributes[:boot_order]
options[:bootOrder] = boot_order(attributes[:boot_order], vm_nics, vm_volumes)
end

# Set attributes[:boot_retry] to a delay in miliseconds to enable boot retries
if attributes[:boot_retry]
options[:bootRetryEnabled] = true
options[:bootRetryDelay] = attributes[:boot_retry]
end

options.empty? ? nil : RbVmomi::VIM::VirtualMachineBootOptions.new(options)
end

def update_volume_attributes(vm_volume, fog_volume)
vm_volume.capacityInKB = fog_volume.size
vm_volume.backing.diskMode = fog_volume.mode
Expand Down
12 changes: 4 additions & 8 deletions tests/requests/compute/create_vm_tests.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,13 @@
RbVmomi::VIM::VirtualMachineBootOptionsBootableEthernetDevice.expects(:new).with(deviceKey: 4002).returns(nwrk_boot3)

expect(
compute.send(:boot_order, { boot_order: ['network'], interfaces: networks }, {})
compute.send(:boot_order, ['network'], networks, [])
).must_equal([nwrk_boot1, nwrk_boot2, nwrk_boot3])
end

it 'adds all disks in order for disk boot' do
disk_devs = [
{ device: stub('key' => 23) },
{ device: stub('key' => 12) },
{ device: stub('key' => 34) }
]
disk_devs.each { |d| d[:device].expects('is_a?').with(RbVmomi::VIM::VirtualDisk).returns(true) }
disk_devs = [stub('key' => 23), stub('key' => 12), stub('key' => 34)]
disk_devs.each { |d| d.stubs('is_a?').with(RbVmomi::VIM::VirtualDisk).returns(true) }
disk_boot1 = stub
disk_boot2 = stub
disk_boot3 = stub
Expand All @@ -82,7 +78,7 @@
RbVmomi::VIM::VirtualMachineBootOptionsBootableDiskDevice.expects(:new).with(deviceKey: 34).returns(disk_boot3)

expect(
compute.send(:boot_order, { boot_order: ['disk'] }, deviceChange: disk_devs)
compute.send(:boot_order, ['disk'], [], disk_devs)
).must_equal([disk_boot1, disk_boot2, disk_boot3])
end
end
Expand Down

0 comments on commit b609505

Please sign in to comment.