-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
With this commit we implement whatever support for virtual hardware reconfiguration. Namely, we support following operations for VM: - increase/decrease memory - increase/decrease number of cpu cores and sockets - increase disk size - add/remove disk BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1572086 Signed-off-by: Miha Pleško <miha.plesko@xlab.si>
- Loading branch information
1 parent
41b450f
commit 47e6b79
Showing
5 changed files
with
264 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 73 additions & 0 deletions
73
app/models/manageiq/providers/vmware/cloud_manager/vm/reconfigure.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
module ManageIQ::Providers::Vmware::CloudManager::Vm::Reconfigure | ||
# Show Reconfigure VM task | ||
def reconfigurable? | ||
true | ||
end | ||
|
||
def max_cpu_cores_per_socket(_total_vcpus = nil) | ||
128 | ||
end | ||
|
||
def max_total_vcpus | ||
128 | ||
end | ||
|
||
def max_vcpus | ||
128 | ||
end | ||
|
||
def max_memory_mb | ||
4.terabyte / 1.megabyte | ||
end | ||
|
||
def disk_types | ||
['LSI Logic Parallel SCSI'] | ||
end | ||
|
||
def disk_default_type | ||
'LSI Logic Parallel SCSI' | ||
end | ||
|
||
def validate_config_spec(options) | ||
if vm_powered_on? | ||
if options[:number_of_cpus] | ||
number_of_cpus = options[:number_of_cpus].to_i | ||
cores_per_socket = options[:cores_per_socket].to_i | ||
raise MiqException::MiqVmError, 'CPU Hot-Add not enabled' if number_of_cpus != cpu_total_cores && !cpu_hot_add_enabled | ||
raise MiqException::MiqVmError, 'CPU Hot-Remove not enabled' if number_of_cpus < cpu_total_cores && !cpu_hot_remove_enabled | ||
raise MiqException::MiqVmError, 'Cannot change CPU cores per socket on a running VM' if cores_per_socket != cpu_cores_per_socket | ||
end | ||
|
||
if options[:vm_memory] | ||
vm_memory = options[:vm_memory].to_i | ||
raise MiqException::MiqVmError, 'Memory Hot-Add not enabled' if vm_memory > ram_size && !memory_hot_add_enabled | ||
raise MiqException::MiqVmError, 'Cannot remove memory from a running VM' if vm_memory < ram_size | ||
end | ||
end | ||
|
||
raise MiqException::MiqVmError, 'Cannot resize disk of VM with shapshots' if options[:disk_resize] && !snapshots.empty? | ||
end | ||
|
||
def build_config_spec(options) | ||
validate_config_spec(options) | ||
|
||
# Virtual hardware modifications. | ||
new_hw = {} | ||
new_hw[:memory] = { :quantity_mb => options[:vm_memory] } if options[:vm_memory] | ||
new_hw[:cpu] = { :num_cores => options[:number_of_cpus], :cores_per_socket => options[:cores_per_socket] } if options[:number_of_cpus] | ||
if (%i(disk_add disk_resize disk_remove) & options.keys).any? | ||
new_hw[:disk] = [] | ||
Array(options[:disk_add]) .each_with_object(new_hw[:disk]) { |d, res| res << { :capacity_mb => d[:disk_size_in_mb].to_i } } | ||
Array(options[:disk_resize]).each_with_object(new_hw[:disk]) { |d, res| res << { :id => disk_id(d[:disk_name]), :capacity_mb => d[:disk_size_in_mb].to_i } } | ||
Array(options[:disk_remove]).each_with_object(new_hw[:disk]) { |d, res| res << { :id => disk_id(d[:disk_name]), :capacity_mb => -1 } } | ||
end | ||
|
||
new_hw.empty? ? {} : { :hardware => new_hw } | ||
end | ||
|
||
def disk_id(disk_name) | ||
disk = disks.detect { |d| d.filename == disk_name } | ||
# Disk location is stored as "{addr}/{parent_addr}/{disk_id}" e.g. "0/3/2000" | ||
disk.location.to_s.split('/').last | ||
end | ||
end |
142 changes: 142 additions & 0 deletions
142
spec/models/manageiq/providers/vmware/cloud_manager/vm/reconfigure_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
describe ManageIQ::Providers::Vmware::CloudManager::Vm::Reconfigure do | ||
let(:vm) do | ||
FactoryGirl.create( | ||
:vm_vmware_cloud, | ||
:name => 'test_vm', | ||
:raw_power_state => 'off', | ||
:cpu_hot_add_enabled => true, | ||
:cpu_hot_remove_enabled => true, | ||
:memory_hot_add_enabled => true, | ||
:hardware => FactoryGirl.create( | ||
:hardware, | ||
:cpu4x2, | ||
:ram1GB, | ||
:disks => [ | ||
FactoryGirl.create(:disk, :size => 1024, :filename => 'Disk 0', :location => '0/1/2000'), | ||
FactoryGirl.create(:disk, :size => 2048, :filename => 'Disk 1', :location => '0/2/2001'), | ||
] | ||
) | ||
) | ||
end | ||
|
||
it '#reconfigurable?' do | ||
expect(vm.reconfigurable?).to be_truthy | ||
end | ||
|
||
describe '#build_config_spec' do | ||
let(:fog_options) { vm.build_config_spec(options) } | ||
let(:options) do | ||
{ | ||
:vm_memory => 16_384, | ||
:cores_per_socket => 2, | ||
:number_of_cpus => 16, | ||
:disk_add => [{ :disk_size_in_mb => '4096' }], | ||
:disk_resize => [{ :disk_name => 'Disk 0', :disk_size_in_mb => '6144' }], | ||
:disk_remove => [{ :disk_name => 'Disk 1' }], | ||
} | ||
end | ||
|
||
describe 'no hardware changes' do | ||
let(:options) { {} } | ||
|
||
it 'fog request optimized' do | ||
expect(fog_options).to eq({}) | ||
end | ||
end | ||
|
||
context 'VM off' do | ||
it 'memory' do | ||
expect(fog_options[:hardware][:memory][:quantity_mb]).to eq(16_384) | ||
end | ||
|
||
describe 'cpu' do | ||
it 'num_cores' do | ||
expect(fog_options[:hardware][:cpu][:num_cores]).to eq(16) | ||
end | ||
|
||
it 'cores_per_socket' do | ||
expect(fog_options[:hardware][:cpu][:cores_per_socket]).to eq(2) | ||
end | ||
end | ||
|
||
describe 'disks' do | ||
it 'add' do | ||
expect(fog_options[:hardware][:disk]).to include(:capacity_mb => 4096) | ||
end | ||
|
||
it 'resize' do | ||
expect(fog_options[:hardware][:disk]).to include(:id => '2000', :capacity_mb => 6144) | ||
end | ||
|
||
it 'remove' do | ||
expect(fog_options[:hardware][:disk]).to include(:id => '2001', :capacity_mb => -1) | ||
end | ||
end | ||
end | ||
|
||
context 'VM on' do | ||
before { vm.raw_power_state = 'on' } | ||
|
||
describe 'memory' do | ||
it 'add memory' do | ||
expect(fog_options[:hardware][:memory][:quantity_mb]).to eq(16_384) | ||
end | ||
|
||
it 'remove memory' do | ||
options[:vm_memory] = 512 | ||
expect { fog_options }.to raise_error(MiqException::MiqVmError, 'Cannot remove memory from a running VM') | ||
end | ||
end | ||
|
||
describe 'cpu' do | ||
it 'add cores' do | ||
expect(fog_options[:hardware][:cpu][:num_cores]).to eq(16) | ||
end | ||
|
||
it 'add cores per socket' do | ||
expect(fog_options[:hardware][:cpu][:cores_per_socket]).to eq(2) | ||
end | ||
|
||
it 'remove cores per socket' do | ||
options[:cores_per_socket] = 1 | ||
expect { fog_options }.to raise_error(MiqException::MiqVmError, 'Cannot change CPU cores per socket on a running VM') | ||
end | ||
end | ||
|
||
describe 'hot memory disabled' do | ||
before { vm.memory_hot_add_enabled = false } | ||
|
||
it 'add memory' do | ||
expect { fog_options }.to raise_error(MiqException::MiqVmError, 'Memory Hot-Add not enabled') | ||
end | ||
end | ||
|
||
describe 'hot cpu add disabled' do | ||
before { vm.cpu_hot_add_enabled = false } | ||
|
||
it 'add cores' do | ||
expect { fog_options }.to raise_error(MiqException::MiqVmError, 'CPU Hot-Add not enabled') | ||
end | ||
end | ||
|
||
describe 'hot cpu remove disabled' do | ||
before { vm.cpu_hot_remove_enabled = false } | ||
|
||
it 'remove cores' do | ||
options[:number_of_cpus] = 1 | ||
expect { fog_options }.to raise_error(MiqException::MiqVmError, 'CPU Hot-Remove not enabled') | ||
end | ||
end | ||
end | ||
|
||
context 'VM with snapshot' do | ||
before { FactoryGirl.create(:snapshot_without_oncreate, :vm_or_template => vm) } | ||
|
||
describe 'disks' do | ||
it 'resize' do | ||
expect { fog_options }.to raise_error(MiqException::MiqVmError, 'Cannot resize disk of VM with shapshots') | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters