Skip to content

Commit dff20ee

Browse files
committed
Implement remove_from_provider/check_removed_from_provider
1 parent e42e7b3 commit dff20ee

File tree

6 files changed

+154
-12
lines changed

6 files changed

+154
-12
lines changed

app/models/miq_retire_task/state_machine.rb

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,31 @@ def run_retire
77

88
def start_retirement
99
if source.retired?
10-
fail!("#{self.class.model_being_retired} already retired")
10+
return fail!("#{self.class.model_being_retired} already retired")
1111
elsif source.retiring?
12-
fail!("#{self.class.model_being_retired} already in the process of being retired")
12+
return fail!("#{self.class.model_being_retired} already in the process of being retired")
1313
end
1414

1515
create_retiring_notification!
1616
source.start_retirement
17+
signal :remove_from_provider
18+
end
19+
20+
def remove_from_provider
21+
signal :check_removed_from_provider
22+
end
23+
24+
def check_removed_from_provider
1725
signal :finish_retirement
1826
end
1927

2028
def finish_retirement
2129
source.finish_retirement
2230
create_retired_notification!
31+
signal :delete_from_vmdb
32+
end
33+
34+
def delete_from_vmdb
2335
signal :finish
2436
end
2537

app/models/orchestration_stack_retire_task.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
class OrchestrationStackRetireTask < MiqRetireTask
2+
include StateMachine
3+
24
default_value_for :request_type, "orchestration_stack_retire"
35

6+
def stack
7+
source
8+
end
9+
410
def self.base_model
511
OrchestrationStackRetireTask
612
end
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module OrchestrationStackRetireTask::StateMachine
2+
extend ActiveSupport::Concern
3+
4+
def remove_from_provider
5+
stack.raw_delete_stack if stack.raw_exists?
6+
7+
signal :check_removed_from_provider
8+
end
9+
10+
def check_removed_from_provider
11+
status, _reason = stack.normalized_live_status
12+
if status == 'not_exist' || status == 'delete_complete'
13+
signal :finish_retirement
14+
else
15+
stack.queue_refresh
16+
requeue_phase
17+
end
18+
end
19+
end

app/models/vm_retire_task/state_machine.rb

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,59 @@ def run_retire
77

88
def check_vm_power_state
99
if vm.power_state != "off"
10-
_log.info("Powering Off VM <#{vm.name}> in provider <#{vm.ext_management_system&.name}>")
10+
_log.info("#{log_prefix} is running, powering off...")
1111
vm.stop
1212
signal :poll_vm_stopped
1313
else
14-
_log.info("VM <#{vm.name}> stopped, retiring...")
14+
_log.info("#{log_prefix} is stopped, retiring...")
1515
signal :start_retirement
1616
end
1717
end
1818

1919
def poll_vm_stopped
20-
_log.info("VM:<#{vm.name}> on Provider:<#{vm.ext_management_system&.name}> has Power State:<#{vm.power_state}>")
20+
_log.info("#{log_prefix} has Power State:<#{vm.power_state}>")
2121

2222
if vm.power_state != "off"
23-
_log.info("VM:<#{vm.name}> on Provider:<#{vm.ext_management_system&.name}> has not stopped")
23+
_log.info("#{log_prefix} has not stopped")
2424
requeue_phase
2525
else
26-
_log.info("VM:<#{vm.name}> on Provider:<#{vm.ext_management_system&.name}> has stopped, retiring...")
26+
_log.info("#{log_prefix} has stopped, retiring...")
2727
signal :start_retirement
2828
end
2929
end
30+
31+
def remove_from_provider
32+
case options[:removal_type]
33+
when "remove_from_disk"
34+
if vm.miq_provision || vm.is_tagged_with?("retire_full", :ns => "/managed/lifecycle")
35+
_log.info("#{log_prefix} Removing from disk...")
36+
vm.remove_from_disk(false)
37+
else
38+
_log.info("#{log_prefix} was not provisioned by us, not removing from disk")
39+
end
40+
when "unregister"
41+
_log.info("#{log_prefix} Unregistering...")
42+
vm.unregister
43+
else
44+
_log.error("#{log_prefix} Unknown retirement type [#{options[:removal_type]}]")
45+
return fail!("Unknown retirement type")
46+
end
47+
48+
signal :check_removed_from_provider
49+
end
50+
51+
def check_removed_from_provider
52+
if vm.ext_management_system
53+
_log.info("#{log_prefix} not yet removed from provider...")
54+
vm.queue_refresh
55+
requeue_phase
56+
else
57+
_log.info("#{log_prefix} removed from provider...")
58+
signal :finish_retirement
59+
end
60+
end
61+
62+
def log_prefix
63+
"VM:<#{vm.name}> on Provider:<#{vm.ext_management_system&.name}>"
64+
end
3065
end

spec/models/orchestration_stack_retire_task_spec.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,12 @@
3232
end
3333

3434
describe "#run_retire" do
35-
before { NotificationType.seed }
35+
before do
36+
NotificationType.seed
37+
expect(orchestration_stack).to receive(:raw_exists?).and_return(true)
38+
expect(orchestration_stack).to receive(:raw_delete_stack)
39+
expect(orchestration_stack).to receive(:normalized_live_status).and_return("delete_complete")
40+
end
3641

3742
it "creates notifications" do
3843
orchestration_stack_retire_task.run_retire

spec/models/vm_retire_task_spec.rb

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
RSpec.describe VmRetireTask do
22
let(:user) { FactoryBot.create(:user_with_group) }
3-
let(:vm) { FactoryBot.create(:vm, :raw_power_state => power_state) }
3+
let(:ems) { FactoryBot.create(:ext_management_system) }
4+
let(:vm) { FactoryBot.create(:vm, :ext_management_system => ems, :raw_power_state => power_state) }
45
let!(:miq_server) { EvmSpecHelper.local_miq_server }
56
let(:miq_request) { FactoryBot.create(:vm_retire_request, :requester => user) }
6-
let(:vm_retire_task) { FactoryBot.create(:vm_retire_task, :source => vm, :miq_request => miq_request, :options => {:src_ids => [vm.id]}) }
7+
let(:vm_retire_task) { FactoryBot.create(:vm_retire_task, :source => vm, :miq_request => miq_request, :options => task_options) }
8+
let(:task_options) { {:src_ids => [vm.id]} }
79
let(:approver) { FactoryBot.create(:user_miq_request_approver) }
810
let(:power_state) { "unknown" }
911

@@ -84,7 +86,7 @@
8486
before { NotificationType.seed }
8587

8688
it "creates a vm_retiring notification" do
87-
expect(vm_retire_task).to receive(:finish_retirement)
89+
expect(vm_retire_task).to receive(:remove_from_provider)
8890
vm_retire_task.signal(:start_retirement)
8991

9092
vm_retiring_notifications = Notification.of_type(:vm_retiring)
@@ -93,7 +95,7 @@
9395
end
9496

9597
it "start the vm retirement process" do
96-
expect(vm_retire_task).to receive(:finish_retirement)
98+
expect(vm_retire_task).to receive(:remove_from_provider)
9799
vm_retire_task.signal(:start_retirement)
98100
expect(vm.reload.retirement_state).to eq("retiring")
99101
end
@@ -125,6 +127,69 @@
125127
end
126128
end
127129

130+
describe "#remove_from_provider" do
131+
context "with removal_type=remove_from_disk" do
132+
let(:task_options) { {:src_ids => [vm.id], :removal_type => "remove_from_disk"} }
133+
134+
it "doesn't delete from disk if we didn't provision it" do
135+
expect(vm).not_to receive(:remove_from_disk)
136+
expect(vm_retire_task).to receive(:check_removed_from_provider)
137+
vm_retire_task.signal(:remove_from_provider)
138+
end
139+
140+
context "with tag lifecycle retire_full" do
141+
before { vm.tag_with("retire_full", :ns => "/managed/lifecycle") }
142+
143+
it "calls remove_from_disk" do
144+
expect(vm).to receive(:remove_from_disk)
145+
expect(vm_retire_task).to receive(:check_removed_from_provider)
146+
vm_retire_task.signal(:remove_from_provider)
147+
end
148+
end
149+
end
150+
151+
context "with removal_type=unregister" do
152+
let(:task_options) { {:src_ids => [vm.id], :removal_type => "unregister"} }
153+
154+
it "calls unregister" do
155+
expect(vm).to receive(:unregister)
156+
expect(vm_retire_task).to receive(:check_removed_from_provider)
157+
vm_retire_task.signal(:remove_from_provider)
158+
end
159+
end
160+
161+
context "with missing removal_type" do
162+
it "raises an exception" do
163+
vm_retire_task.signal(:remove_from_provider)
164+
expect(vm_retire_task.reload).to have_attributes(
165+
:state => "finished",
166+
:status => "Error",
167+
:message => "Unknown retirement type"
168+
)
169+
end
170+
end
171+
end
172+
173+
describe "#check_removed_from_provider" do
174+
context "with an active vm" do
175+
it "queues a refresh and requeues the state" do
176+
expect(vm_retire_task).not_to receive(:finish_retirement)
177+
vm_retire_task.signal(:check_removed_from_provider)
178+
expect(vm_retire_task.reload.phase).to eq("check_removed_from_provider")
179+
expect(MiqQueue.first).to have_attributes(:class_name => described_class.name, :method_name => "check_removed_from_provider")
180+
end
181+
end
182+
183+
context "with an archived vm" do
184+
let(:vm) { FactoryBot.create(:vm, :ext_management_system => nil, :raw_power_state => power_state) }
185+
186+
it "signals finish_retirement" do
187+
expect(vm_retire_task).to receive(:finish_retirement)
188+
vm_retire_task.signal(:check_removed_from_provider)
189+
end
190+
end
191+
end
192+
128193
describe "#finish_retirement" do
129194
before do
130195
NotificationType.seed

0 commit comments

Comments
 (0)