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
JobProxyDispatcher should use all container image classes #15519
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
class JobProxyDispatcher | ||
include Vmdb::Logging | ||
|
||
def self.dispatch | ||
new.dispatch | ||
end | ||
|
@@ -93,6 +94,10 @@ def dispatch | |
_log.info "Complete - Timings: #{t.inspect}" | ||
end | ||
|
||
def container_image_classes | ||
ContainerImage.descendants.append(ContainerImage) | ||
end | ||
|
||
def dispatch_container_scan_jobs | ||
jobs_by_ems, = Benchmark.realtime_block(:pending_container_jobs) { pending_container_jobs } | ||
Benchmark.current_realtime[:container_jobs_to_dispatch_count] = jobs_by_ems.values.reduce(0) { |m, o| m + o.length } | ||
|
@@ -193,12 +198,11 @@ def self.waiting? | |
end | ||
|
||
def pending_jobs(target_class = VmOrTemplate) | ||
class_name = target_class.base_class.name | ||
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. any idea what was the result of this line? 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. For both |
||
@zone = MiqServer.my_zone | ||
Job.order(:id) | ||
.where(:state => "waiting_to_start") | ||
.where(:dispatch_status => "pending") | ||
.where(:target_class => class_name) | ||
.where(:target_class => target_class) | ||
.where("zone is null or zone = ?", @zone) | ||
.where("sync_key is NULL or | ||
sync_key not in ( | ||
|
@@ -210,7 +214,7 @@ def pending_jobs(target_class = VmOrTemplate) | |
end | ||
|
||
def pending_container_jobs | ||
pending_jobs(ContainerImage).each_with_object(Hash.new { |h, k| h[k] = [] }) do |job, h| | ||
pending_jobs(container_image_classes).each_with_object(Hash.new { |h, k| h[k] = [] }) do |job, h| | ||
h[job.options[:ems_id]] << job | ||
end | ||
end | ||
|
@@ -254,9 +258,8 @@ def busy_proxies | |
end | ||
|
||
def active_scans_by_zone(target_class, count = true) | ||
class_name = target_class.base_class.name | ||
actives = Hash.new(0) | ||
jobs = Job.where(:zone => @zone, :dispatch_status => "active", :target_class => class_name) | ||
jobs = Job.where(:zone => @zone, :dispatch_status => "active", :target_class => target_class) | ||
.where.not(:state => "finished") | ||
actives[@zone] = count ? jobs.count : jobs | ||
actives | ||
|
@@ -271,7 +274,7 @@ def active_container_scans_by_zone_and_ems | |
memo = Hash.new do |h, k| | ||
h[k] = Hash.new(0) | ||
end | ||
active_scans_by_zone(ContainerImage, false)[@zone].each do |job| | ||
active_scans_by_zone(container_image_classes, false)[@zone].each do |job| | ||
memo[@zone][job.options[:ems_id]] += 1 | ||
end | ||
memo | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -174,6 +174,7 @@ | |
end | ||
|
||
context "with container and vms jobs" do | ||
let (:container_image_classes) { ContainerImage.descendants.collect(&:name).append('ContainerImage') } | ||
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. please test for a list as well 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. |
||
before(:each) do | ||
@jobs = (@vms + @repo_vms).collect(&:raw_scan) | ||
User.current_user = FactoryGirl.create(:user) | ||
|
@@ -191,10 +192,10 @@ | |
end | ||
|
||
it "returns only container images jobs when requested" do | ||
jobs = dispatcher.pending_jobs(ContainerImage) | ||
jobs = dispatcher.pending_jobs(dispatcher.container_image_classes) | ||
expect(jobs.count).to eq(@container_images.count) | ||
jobs.each do |x| | ||
expect(x.target_class).to eq 'ContainerImage' | ||
expect(container_image_classes).to include x.target_class | ||
end | ||
expect(jobs.count).to be > 0 # in case something unexpected goes wrong | ||
end | ||
|
@@ -212,7 +213,7 @@ | |
|
||
describe "#active_container_scans_by_zone_and_ems" do | ||
it "returns active container acans for zone" do | ||
job = @jobs.find { |j| j.target_class == ContainerImage.name } | ||
job = @jobs.find { |j| container_image_classes.include?(j.target_class) } | ||
job.update(:dispatch_status => "active") | ||
provider = ExtManagementSystem.find(job.options[:ems_id]) | ||
dispatcher.instance_variable_set(:@zone, MiqServer.my_zone) # memoized during pending_jobs call | ||
|
@@ -226,29 +227,29 @@ | |
it "dispatches jobs until reaching limit" do | ||
stub_settings(:container_scanning => {:concurrent_per_ems => 1}) | ||
dispatcher.dispatch_container_scan_jobs | ||
expect(Job.where(:target_class => ContainerImage, :dispatch_status => "pending").count).to eq(1) | ||
expect(Job.where(:target_class => container_image_classes, :dispatch_status => "pending").count).to eq(1) | ||
# 1 per ems, one ems has 1 job and the other 2 | ||
end | ||
|
||
it "does not dispach if limit is already reached" do | ||
stub_settings(:container_scanning => {:concurrent_per_ems => 1}) | ||
dispatcher.dispatch_container_scan_jobs | ||
expect(Job.where(:target_class => ContainerImage, :dispatch_status => "pending").count).to eq(1) | ||
expect(Job.where(:target_class => container_image_classes, :dispatch_status => "pending").count).to eq(1) | ||
dispatcher.dispatch_container_scan_jobs | ||
expect(Job.where(:target_class => ContainerImage, :dispatch_status => "pending").count).to eq(1) | ||
expect(Job.where(:target_class => container_image_classes, :dispatch_status => "pending").count).to eq(1) | ||
end | ||
|
||
it "does not apply limit when concurrent_per_ems is 0" do | ||
stub_settings(:container_scanning => {:concurrent_per_ems => 0}) | ||
dispatcher.dispatch_container_scan_jobs | ||
expect(Job.where(:target_class => ContainerImage, :dispatch_status => "pending").count).to eq(0) | ||
expect(Job.where(:target_class => container_image_classes, :dispatch_status => "pending").count).to eq(0) | ||
# 1 per ems, one ems has 1 job and the other 2 | ||
end | ||
|
||
it "does not apply limit when concurrent_per_ems is -1" do | ||
stub_settings(:container_scanning => {:concurrent_per_ems => -1}) | ||
dispatcher.dispatch_container_scan_jobs | ||
expect(Job.where(:target_class => ContainerImage, :dispatch_status => "pending").count).to eq(0) | ||
expect(Job.where(:target_class => container_image_classes, :dispatch_status => "pending").count).to eq(0) | ||
# 1 per ems, one ems has 1 job and the other 2 | ||
end | ||
end | ||
|
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 know the current pattern does this but it feels like the dispatcher shouldn't have this knowledge. Additionally, it would cause us to load each of these classes and any requires they do in the schedule worker... a process that probably shouldn't load container dependencies. I'm not sure of a better solution but if you have an idea, do let us know.
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.
It is a hack, maybe if we add a comment that states that if we ever get a target that isn't one of the two we should rethink.
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.
hi @moolitayer, thanks... One thing that still confuses me is it feels like the vm scans are really VmOrTemplateScanJob things (hiding as the Job class) and the container image scans are really ContainerImageScanJob things (hiding as a list of descendent classes + self here)... I don't know why we didn't use single table inheritance on this table in the past but I'm wondering if we should do it now. Perhaps fix this without a migration like you are here for any backports... but then, fix it right on master with STI. What do you think? cc @Fryguy
The nice thing is then you can do ContainerImageScanJob.where... or VmOrTemplateScanJob.where as you would expect. This might break the UI in many places where they're expecting Job classes by name, but it feels like we're doing it the hard way and fixing this might help maintenance in the future.
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.
@gtanzillo ^
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.
We already do have STI on the jobs table.