Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[V2V] Add restoring_vm_attributes state to InfraConversionJob #19240

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 46 additions & 2 deletions app/models/infra_conversion_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ def load_transitions
'waiting_for_inventory_refresh' => 'waiting_for_inventory_refresh'
},
:apply_right_sizing => {'waiting_for_inventory_refresh' => 'applying_right_sizing'},
:restore_vm_attributes => {'applying_right_sizing' => 'restoring_vm_attributes'},
:poll_automate_state_machine => {
'applying_right_sizing' => 'running_in_automate',
'running_in_automate' => 'running_in_automate'
'restoring_vm_attributes' => 'running_in_automate',
'running_in_automate' => 'running_in_automate'
},
:finish => {'*' => 'finished'},
:abort_job => {'*' => 'aborting'},
Expand Down Expand Up @@ -98,6 +99,10 @@ def state_settings
:description => "Apply Right-Sizing Recommendation",
:weight => 1
},
:restoring_vm_attributes => {
:description => "Restore VM Attributes",
:weight => 1
},
:running_in_automate => {
:max_retries => 36.hours / state_retry_interval
}
Expand Down Expand Up @@ -445,6 +450,45 @@ def apply_right_sizing
send("apply_right_sizing_#{item}", right_sizing_mode) if right_sizing_mode.present?
end

update_migration_task_progress(:on_exit)
queue_signal(:restore_vm_attributes)
rescue StandardError
update_migration_task_progress(:on_error)
queue_signal(:restore_vm_attributes)
end

def restore_vm_attributes
update_migration_task_progress(:on_entry)

# Transfer service link to destination VM
if source_vm.service
destination_vm.add_to_service(source_vm.service)
source_vm.direct_service.try(:remove_resource, source_vm)
end

# Copy tags and custom attributes from source VM
source_vm.tags.each do |tag|
next if tag.name =~ /^\/managed\/folder_path_/

tag_as_array = tag.name.split('/')
namespace = tag_as_array.shift
value = tag_as_array.pop
category = tag_as_array.join('/')
destination_vm.tag_add("#{category}/#{value}", :ns => namespace)
end
source_vm.miq_custom_keys.each { |ca| destination_vm.miq_custom_set(ca, source_vm.miq_custom_get(ca)) }

# Copy ownership from source VM
destination_vm.evm_owner = source_vm.evm_owner if source_vm.present?
destination_vm.miq_group = source_vm.miq_group if source_vm.miq_group.present?

# Copy retirement settings from source VM
destination_vm.retires_on = source_vm.retires_on if source_vm.retires_on.present?
destination_vm.retirement_warn = source_vm.retirement_warn if source_vm.retirement_warn.present?

# Save destination_vm in VMDB
destination_vm.save

update_migration_task_progress(:on_exit)
handover_to_automate
queue_signal(:poll_automate_state_machine)
Expand Down
107 changes: 97 additions & 10 deletions spec/models/infra_conversion_job_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
RSpec.describe InfraConversionJob, :v2v do
let(:user) { FactoryBot.create(:user_with_group) }
let(:user_admin) { FactoryBot.create(:user_admin) }
let(:group) { FactoryBot.create(:miq_group) }
let(:zone) { FactoryBot.create(:zone) }

let(:ems_vmware) { FactoryBot.create(:ems_vmware, :zone => zone) }
Expand All @@ -15,13 +17,14 @@
:ems_cluster => ems_cluster_vmware,
:host => host_vmware,
:hardware => hardware_vmware,
:evm_owner => user)
:evm_owner => user,
:miq_group => group)
end

let(:ems_redhat) { FactoryBot.create(:ems_redhat, :zone => zone) }
let(:ems_cluster_redhat) { FactoryBot.create(:ems_cluster, :ext_management_system => ems_redhat) }
let(:host_redhat) { FactoryBot.create(:host, :ext_management_system => ems_redhat, :ems_cluster => ems_cluster_redhat) }
let(:vm_redhat) { FactoryBot.create(:vm_vmware, :ext_management_system => ems_redhat, :ems_cluster => ems_cluster_redhat, :host => host_redhat, :evm_owner => user) }
let(:vm_redhat) { FactoryBot.create(:vm_vmware, :ext_management_system => ems_redhat, :ems_cluster => ems_cluster_redhat, :host => host_redhat, :evm_owner => user_admin) }

let(:embedded_ansible_auth) { FactoryBot.create(:embedded_ansible_credential) }
let(:embedded_ansible_catalog_item_options) do
Expand Down Expand Up @@ -349,7 +352,7 @@
end

context 'state transitions' do
%w[start remove_snapshots poll_remove_snapshots_complete wait_for_ip_address run_migration_playbook poll_run_migration_playbook_complete shutdown_vm poll_shutdown_vm_complete transform_vm poll_transform_vm_complete poll_inventory_refresh_complete apply_right_sizing poll_automate_state_machine finish abort_job cancel error].each do |signal|
%w[start remove_snapshots poll_remove_snapshots_complete wait_for_ip_address run_migration_playbook poll_run_migration_playbook_complete shutdown_vm poll_shutdown_vm_complete transform_vm poll_transform_vm_complete poll_inventory_refresh_complete apply_right_sizing restore_vm_attributes poll_automate_state_machine finish abort_job cancel error].each do |signal|
shared_examples_for "allows #{signal} signal" do
it signal.to_s do
expect(job).to receive(signal.to_sym)
Expand All @@ -358,7 +361,7 @@
end
end

%w[start remove_snapshots poll_remove_snapshots_complete wait_for_ip_address run_migration_playbook poll_run_migration_playbook_complete shutdown_vm poll_shutdown_vm_complete transform_vm poll_transform_vm_complete poll_inventory_refresh_complete apply_right_sizing poll_automate_state_machine].each do |signal|
%w[start remove_snapshots poll_remove_snapshots_complete wait_for_ip_address run_migration_playbook poll_run_migration_playbook_complete shutdown_vm poll_shutdown_vm_complete transform_vm poll_transform_vm_complete poll_inventory_refresh_complete apply_right_sizing restore_vm_attributes poll_automate_state_machine].each do |signal|
shared_examples_for "doesn't allow #{signal} signal" do
it signal.to_s do
expect { job.signal(signal.to_sym) }.to raise_error(RuntimeError, /#{signal} is not permitted at state #{job.state}/)
Expand Down Expand Up @@ -387,6 +390,8 @@
it_behaves_like 'doesn\'t allow transform_vm signal'
it_behaves_like 'doesn\'t allow poll_transform_vm_complete signal'
it_behaves_like 'doesn\'t allow poll_inventory_refresh_complete signal'
it_behaves_like 'doesn\'t allow apply_right_sizing signal'
it_behaves_like 'doesn\'t allow restore_vm_attributes signal'
it_behaves_like 'doesn\'t allow poll_automate_state_machine signal'
end

Expand All @@ -411,6 +416,8 @@
it_behaves_like 'doesn\'t allow transform_vm signal'
it_behaves_like 'doesn\'t allow poll_transform_vm_complete signal'
it_behaves_like 'doesn\'t allow poll_inventory_refresh_complete signal'
it_behaves_like 'doesn\'t allow apply_right_sizing signal'
it_behaves_like 'doesn\'t allow restore_vm_attributes signal'
it_behaves_like 'doesn\'t allow poll_automate_state_machine signal'
end

Expand All @@ -435,6 +442,8 @@
it_behaves_like 'doesn\'t allow transform_vm signal'
it_behaves_like 'doesn\'t allow poll_transform_vm_complete signal'
it_behaves_like 'doesn\'t allow poll_inventory_refresh_complete signal'
it_behaves_like 'doesn\'t allow apply_right_sizing signal'
it_behaves_like 'doesn\'t allow restore_vm_attributes signal'
it_behaves_like 'doesn\'t allow poll_automate_state_machine signal'
end

Expand All @@ -459,6 +468,8 @@
it_behaves_like 'doesn\'t allow transform_vm signal'
it_behaves_like 'doesn\'t allow poll_transform_vm_complete signal'
it_behaves_like 'doesn\'t allow poll_inventory_refresh_complete signal'
it_behaves_like 'doesn\'t allow apply_right_sizing signal'
it_behaves_like 'doesn\'t allow restore_vm_attributes signal'
it_behaves_like 'doesn\'t allow poll_automate_state_machine signal'
end

Expand All @@ -483,6 +494,8 @@
it_behaves_like 'doesn\'t allow transform_vm signal'
it_behaves_like 'doesn\'t allow poll_transform_vm_complete signal'
it_behaves_like 'doesn\'t allow poll_inventory_refresh_complete signal'
it_behaves_like 'doesn\'t allow apply_right_sizing signal'
it_behaves_like 'doesn\'t allow restore_vm_attributes signal'
it_behaves_like 'doesn\'t allow poll_automate_state_machine signal'
end

Expand All @@ -507,6 +520,8 @@
it_behaves_like 'doesn\'t allow shutdown_vm signal'
it_behaves_like 'doesn\'t allow poll_transform_vm_complete signal'
it_behaves_like 'doesn\'t allow poll_inventory_refresh_complete signal'
it_behaves_like 'doesn\'t allow apply_right_sizing signal'
it_behaves_like 'doesn\'t allow restore_vm_attributes signal'
it_behaves_like 'doesn\'t allow poll_automate_state_machine signal'
end

Expand All @@ -531,6 +546,8 @@
it_behaves_like 'doesn\'t allow shutdown_vm signal'
it_behaves_like 'doesn\'t allow poll_shutdown_vm_complete signal'
it_behaves_like 'doesn\'t allow transform_vm signal'
it_behaves_like 'doesn\'t allow apply_right_sizing signal'
it_behaves_like 'doesn\'t allow restore_vm_attributes signal'
it_behaves_like 'doesn\'t allow poll_automate_state_machine signal'
end

Expand All @@ -556,13 +573,39 @@
it_behaves_like 'doesn\'t allow poll_shutdown_vm_complete signal'
it_behaves_like 'doesn\'t allow transform_vm signal'
it_behaves_like 'doesn\'t allow poll_transform_vm_complete signal'
it_behaves_like 'doesn\'t allow restore_vm_attributes signal'
end

context 'applying_right_sizing' do
before do
job.state = 'applying_right_sizing'
end

it_behaves_like 'allows restore_vm_attributes signal'
it_behaves_like 'allows finish signal'
it_behaves_like 'allows abort_job signal'
it_behaves_like 'allows cancel signal'
it_behaves_like 'allows error signal'

it_behaves_like 'doesn\'t allow start signal'
it_behaves_like 'doesn\'t allow remove_snapshots signal'
it_behaves_like 'doesn\'t allow poll_remove_snapshots_complete signal'
it_behaves_like 'doesn\'t allow wait_for_ip_address signal'
it_behaves_like 'doesn\'t allow run_migration_playbook signal'
it_behaves_like 'doesn\'t allow poll_run_migration_playbook_complete signal'
it_behaves_like 'doesn\'t allow shutdown_vm signal'
it_behaves_like 'doesn\'t allow poll_shutdown_vm_complete signal'
it_behaves_like 'doesn\'t allow transform_vm signal'
it_behaves_like 'doesn\'t allow poll_transform_vm_complete signal'
it_behaves_like 'doesn\'t allow poll_inventory_refresh_complete signal'
it_behaves_like 'doesn\'t allow apply_right_sizing signal'
end

context 'restoring_vm_attributes' do
before do
job.state = 'restoring_vm_attributes'
end

it_behaves_like 'allows poll_automate_state_machine signal'
it_behaves_like 'allows finish signal'
it_behaves_like 'allows abort_job signal'
Expand All @@ -581,6 +624,7 @@
it_behaves_like 'doesn\'t allow poll_transform_vm_complete signal'
it_behaves_like 'doesn\'t allow poll_inventory_refresh_complete signal'
it_behaves_like 'doesn\'t allow apply_right_sizing signal'
it_behaves_like 'doesn\'t allow restore_vm_attributes signal'
end

context 'running_in_automate' do
Expand All @@ -606,6 +650,7 @@
it_behaves_like 'doesn\'t allow poll_transform_vm_complete signal'
it_behaves_like 'doesn\'t allow poll_inventory_refresh_complete signal'
it_behaves_like 'doesn\'t allow apply_right_sizing signal'
it_behaves_like 'doesn\'t allow restore_vm_attributes signal'
end
end

Expand Down Expand Up @@ -1020,13 +1065,12 @@
task.update!(:destination => vm_redhat)
end

it "exits to next state in case of failed" do
it "exits to next state in case of failure" do
allow(job.migration_task).to receive(:cpu_right_sizing_mode).and_raise('Fake error message')
expect(job).to receive(:update_migration_task_progress).once.ordered.with(:on_entry)
expect(job).to receive(:update_migration_task_progress).once.ordered.with(:on_error)
expect(job).to receive(:queue_signal).with(:poll_automate_state_machine)
expect(job).to receive(:queue_signal).with(:restore_vm_attributes)
job.signal(:apply_right_sizing)
expect(task.reload.options[:workflow_runner]).to eq('automate')
end

context 'without right_sizing mode' do
Expand All @@ -1038,9 +1082,8 @@
it 'exits if no right-sizing is requested' do
expect(job).to receive(:update_migration_task_progress).once.ordered.with(:on_entry)
expect(job).to receive(:update_migration_task_progress).once.ordered.with(:on_exit)
expect(job).to receive(:queue_signal).with(:poll_automate_state_machine)
expect(job).to receive(:queue_signal).with(:restore_vm_attributes)
job.signal(:apply_right_sizing)
expect(task.reload.options[:workflow_runner]).to eq('automate')
end
end

Expand All @@ -1057,8 +1100,52 @@
expect(job.migration_task.destination).to receive(:set_number_of_cpus).with(1)
expect(job.migration_task.destination).to receive(:set_memory).with(1024)
expect(job).to receive(:update_migration_task_progress).once.ordered.with(:on_exit)
expect(job).to receive(:queue_signal).with(:poll_automate_state_machine)
expect(job).to receive(:queue_signal).with(:restore_vm_attributes)
job.signal(:apply_right_sizing)
end
end
end

context '#restore_vm_attributes' do
let(:service) { FactoryBot.create(:service) }
let(:parent_classification) { FactoryBot.create(:classification, :name => 'environment', :description => 'Environment') }
let(:classification) { FactoryBot.create(:classification, :name => 'prod', :description => 'Production', :parent => parent_classication) }

before do
job.state = 'applying_right_sizing'
task.update!(:destination => vm_redhat)
end

it "exits to next state in case of failure" do
allow(job.migration_task.source).to receive(:service).and_raise('Fake error message')
expect(job).to receive(:update_migration_task_progress).once.ordered.with(:on_entry)
expect(job).to receive(:update_migration_task_progress).once.ordered.with(:on_error)
expect(job).to receive(:queue_signal).with(:poll_automate_state_machine)
job.signal(:restore_vm_attributes)
expect(task.reload.options[:workflow_runner]).to eq('automate')
end

it 'restore VM attributes' do
Timecop.freeze(2019, 2, 6) do
vm_vmware.add_to_service(service)
vm_vmware.tag_with('test', :ns => '/managed', :cat => 'folder_path_spec')
vm_vmware.tag_with('prod', :ns => '/managed', :cat => 'environment')
vm_vmware.miq_custom_set('attr', 'value')
vm_vmware.update!(:retires_on => Time.now.utc + 1.day)
vm_vmware.update!(:retirement_warn => 7)
expect(job).to receive(:update_migration_task_progress).once.ordered.with(:on_entry)
expect(job).to receive(:update_migration_task_progress).once.ordered.with(:on_exit)
expect(job).to receive(:queue_signal).with(:poll_automate_state_machine)
job.signal(:restore_vm_attributes)
vm_redhat.reload
expect(vm_vmware.service).to be_nil
expect(vm_redhat.service.id).to eq(service.id)
expect(vm_redhat.tags).to eq(['/managed/environment/prod'])
expect(vm_redhat.miq_custom_get('attr')).to eq('value')
expect(vm_redhat.evm_owner.id).to eq(user.id)
expect(vm_redhat.miq_group.id).to eq(group.id)
expect(vm_redhat.retires_on).to eq(Time.now.utc + 1.day)
expect(vm_redhat.retirement_warn).to eq(7)
expect(task.reload.options[:workflow_runner]).to eq('automate')
end
end
Expand Down