-
Notifications
You must be signed in to change notification settings - Fork 900
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16082 from lfu/service_resource_linking
Add Service resource linking.
- Loading branch information
Showing
5 changed files
with
263 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
class Service | ||
class LinkingWorkflow < ManageIQ::Providers::EmsRefreshWorkflow | ||
def load_transitions | ||
self.state ||= 'initialize' | ||
|
||
{ | ||
:initializing => {'initialize' => 'waiting_to_start'}, | ||
:start => {'waiting_to_start' => 'running'}, | ||
:refresh => {'running' => 'refreshing'}, | ||
:poll_refresh => {'refreshing' => 'refreshing'}, | ||
:post_refresh => { | ||
'running' => 'post_refreshing', | ||
'refreshing' => 'post_refreshing' | ||
}, | ||
:finish => {'*' => 'finished'}, | ||
:abort_job => {'*' => 'aborting'}, | ||
:cancel => {'*' => 'canceling'}, | ||
:error => {'*' => '*'} | ||
} | ||
end | ||
|
||
def run_native_op | ||
_log.info("Enter") | ||
|
||
unless linking_service | ||
msg = "Job [%{id}] [%{name}] aborted: didn't find service ID: [%{service_id}] to link to" % { | ||
:id => id, :name => name, :service_id => options[:service_id] | ||
} | ||
_log.error(msg) | ||
signal(:abort, msg, 'error') | ||
end | ||
|
||
unless target_entity | ||
msg = "Job [%{id}] [%{name}] aborted: didn't find provider class: [%{target_class}] ID: [%{target_id}] to refresh" % { | ||
:id => id, :name => name, :target_class => target_class, :target_id => target_id | ||
} | ||
_log.error(msg) | ||
signal(:abort, msg, 'error') | ||
end | ||
|
||
if find_all_targets? | ||
set_status("all VMs are found in DB") | ||
signal(:post_refresh) | ||
else | ||
set_status("calling refresh") | ||
queue_signal(:refresh) | ||
end | ||
end | ||
alias_method :start, :run_native_op | ||
|
||
def post_refresh | ||
_log.info("Enter") | ||
|
||
found_vms = linking_targets | ||
not_found_vms = options[:uid_ems_array] - found_vms.pluck(:uid_ems) | ||
_log.warn("VMs not found for linking to service ID [#{service.id}], name [#{service.name}]: #{not_found_vms}") unless not_found_vms.blank? | ||
|
||
service = linking_service | ||
found_vms.each { |vm| service.add_resource!(vm) } | ||
signal(:finish, "linking VMs to service is complete", "ok") | ||
rescue => err | ||
_log.log_backtrace(err) | ||
signal(:abort, err.message, "error") | ||
end | ||
|
||
private | ||
|
||
def find_all_targets? | ||
linking_targets.length == options[:uid_ems_array].length | ||
end | ||
|
||
def linking_targets | ||
@linking_targets ||= VmOrTemplate.where(:uid_ems => options[:uid_ems_array], :ems_id => target_id) | ||
end | ||
|
||
def linking_service | ||
@linking_service ||= Service.find_by(:id => options[:service_id]) | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
module Service::ResourceLinking | ||
extend ActiveSupport::Concern | ||
|
||
def add_provider_vms(provider, uid_ems_array) | ||
vm_uid_array = Array(uid_ems_array).compact.uniq | ||
raise _("no uid_ems_array defined for linking to service") if vm_uid_array.blank? | ||
|
||
options = { | ||
:target_class => provider.class.name, | ||
:target_id => provider.id, | ||
:uid_ems_array => vm_uid_array, | ||
:name => "Linking VMs to service #{name} ID: [#{id}]", | ||
:userid => evm_owner.userid, | ||
:sync_key => guid, | ||
:service_id => id, | ||
:zone => my_zone | ||
} | ||
|
||
_log.info("NAME [#{options[:name]}] for user #{evm_owner.userid}") | ||
|
||
Service::LinkingWorkflow.create_job(options).tap do |job| | ||
job.signal(:start) | ||
end | ||
rescue => err | ||
_log.log_backtrace(err) | ||
raise | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
describe Service::LinkingWorkflow do | ||
let(:service) { FactoryGirl.create(:service) } | ||
let(:provider) { FactoryGirl.create(:ems_vmware) } | ||
let(:uid_ems_array) { ["423c9963-378c-813f-1dbd-630e464d59d4", "423cf3e2-e319-3953-993f-fd8513db951d"] } | ||
let(:options) do | ||
{ | ||
:target_class => provider.class.name, | ||
:target_id => provider.id, | ||
:uid_ems_array => uid_ems_array, | ||
:service_id => service.id | ||
} | ||
end | ||
let(:job) { described_class.create_job(options) } | ||
|
||
context 'run_native_op' do | ||
subject { job.run_native_op } | ||
|
||
it 'raises an error if service is not found' do | ||
options[:service_id] = 999 | ||
expect(job).to receive(:signal).with(:abort, "Job [#{job.id}] [#{job.name}] aborted: didn't find service ID: [999] to link to", "error") | ||
subject | ||
end | ||
|
||
it 'raises an error if provider is not found' do | ||
options[:target_id] = 999 | ||
msg = "Job [#{job.id}] [#{job.name}] aborted: didn't find provider class: [#{provider.class.name}] ID: [999] to refresh" | ||
expect(job).to receive(:signal).with(:abort, msg, "error") | ||
subject | ||
end | ||
|
||
it 'calls refresh if not all VMs found in DB' do | ||
expect(job).to receive(:queue_signal).with(:refresh) | ||
subject | ||
end | ||
|
||
it 'calls post_refresh if all VMs found in DB' do | ||
uid_ems_array.each { |uid| FactoryGirl.create(:vm_vmware, :uid_ems => uid, :ems_id => provider.id) } | ||
expect(job).to receive(:signal).with(:post_refresh) | ||
subject | ||
end | ||
end | ||
|
||
context 'post_refresh' do | ||
subject { job.post_refresh } | ||
|
||
it 'links found VMs to service' do | ||
uid_ems_array.each { |uid| FactoryGirl.create(:vm_vmware, :uid_ems => uid, :ems_id => provider.id) } | ||
subject | ||
expect(service.vms.count).to eq(2) | ||
end | ||
end | ||
|
||
context 'state transitions' do | ||
%w(start refresh poll_refresh post_refresh 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) | ||
job.signal(signal.to_sym) | ||
end | ||
end | ||
end | ||
|
||
%w(start refresh poll_refresh post_refresh).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}/) | ||
end | ||
end | ||
end | ||
|
||
context 'waiting_to_start' do | ||
before do | ||
job.state = 'waiting_to_start' | ||
end | ||
|
||
it_behaves_like 'allows start 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 refresh signal' | ||
it_behaves_like 'doesn\'t allow poll_refresh signal' | ||
it_behaves_like 'doesn\'t allow post_refresh signal' | ||
end | ||
|
||
context 'running' do | ||
before do | ||
job.state = 'running' | ||
end | ||
|
||
it_behaves_like 'allows refresh signal' | ||
it_behaves_like 'allows post_refresh 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 poll_refresh signal' | ||
end | ||
|
||
context 'refreshing' do | ||
before do | ||
job.state = 'refreshing' | ||
end | ||
|
||
it_behaves_like 'allows poll_refresh signal' | ||
it_behaves_like 'allows post_refresh 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 refresh signal' | ||
end | ||
|
||
context 'post_refreshing' do | ||
before do | ||
job.state = 'post_refreshing' | ||
end | ||
|
||
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 refresh signal' | ||
it_behaves_like 'doesn\'t allow poll_refresh signal' | ||
it_behaves_like 'doesn\'t allow post_refresh signal' | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
describe Service do | ||
describe '#add_provider_vms' do | ||
let(:service) { FactoryGirl.create(:service, :evm_owner => FactoryGirl.create(:user)) } | ||
let(:provider) { FactoryGirl.create(:ems_vmware) } | ||
let(:uid_ems_array) { ["423c9963-378c-813f-1dbd-630e464d59d4", "423cf3e2-e319-3953-993f-fd8513db951d"] } | ||
|
||
it 'raises an error if uid_ems_array is not passed in' do | ||
expect { service.add_provider_vms(provider, []) }.to raise_error(RuntimeError, "no uid_ems_array defined for linking to service") | ||
end | ||
|
||
it 'creates a Service::LinkingWorkflow job' do | ||
expect(Service::LinkingWorkflow).to receive(:create_job) do |args| | ||
expect(args).to match(hash_including(:target_class => provider.class.name, :target_id => provider.id)) | ||
expect(args).to match(hash_including(:uid_ems_array => array_including(uid_ems_array))) | ||
end.and_return(double(:signal => :start)) | ||
service.add_provider_vms(provider, uid_ems_array) | ||
end | ||
end | ||
end |