-
Notifications
You must be signed in to change notification settings - Fork 897
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
Add Service resource linking. #16082
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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) } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will the job be automatically deleted after test? |
||
|
||
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 |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see
:abort
, but only:abort_job
or:error
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never mind. I saw it in the state_machine mixin.