Skip to content

Commit

Permalink
Add RecurringLogic to update HostResources
Browse files Browse the repository at this point in the history
Add task RefreshResourceQuotaUtilization which calls determine_utilization
on every ResourceQuota. The command iterates all hosts of a ResourceQuota
and sets the host.host_resources which is used for the ResourceQuota.utilization.

This guarantees that Foreman does not miss changes to HostResources,
when they are not performed via the Foreman UI. Moreover, it increases
performance since Foreman Resource Quota does not re-compute a
ResourceQuota's utilization on host deployment and, instead, takes
the last-computed sum of HostResources.

However, this comes with the downside that HostResources might be missed
when edited out-of Foreman UI and new hosts are deployed before the
task is executed.
  • Loading branch information
bastian-src committed Nov 27, 2024
1 parent 0ca279a commit 4885f93
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,7 @@ Rails/SkipsModelValidations:

Style/FormatStringToken:
Enabled: false

Rails/DynamicFindBy:
Exclude:
- "lib/foreman_resource_quota/engine.rb"
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

module ForemanResourceQuota
module Async
class RefreshResourceQuotaUtilization < ::Actions::EntryAction
include ::Actions::RecurringAction

def run
ResourceQuota.all.each do |quota|
quota.determine_utilization
rescue e
logger.error N_(format("An error occured determining the utilization of '%s'-quota: %s", quota.name, e))
end
end

def logger
action_logger
end

def rescue_strategy_for_self
Dynflow::Action::Rescue::Fail
end
end
end
end
40 changes: 40 additions & 0 deletions lib/foreman_resource_quota/engine.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require 'foreman_tasks'

module ForemanResourceQuota
class Engine < ::Rails::Engine
engine_name 'foreman_resource_quota'
Expand Down Expand Up @@ -42,10 +44,48 @@ class Engine < ::Rails::Engine
Rails.logger.warn "ForemanResourceQuota: skipping engine hook (#{e})"
end

# Register ForemanTasks-based recurring logic/scheduled tasks
initializer 'foreman_resource_quota.register_scheduled_tasks', before: :finisher_hook do |_app|
action_paths = [ForemanResourceQuota::Engine.root.join('lib/foreman_resource_quota/async')]
::ForemanTasks.dynflow.config.eager_load_paths.concat(action_paths)

# Skip object creation if the admin user is not present
# skip database manipulations while tables do not exist, like in migrations
if ActiveRecord::Base.connection.data_source_exists?(ForemanTasks::Task.table_name) &&
User.unscoped.find_by_login(User::ANONYMOUS_ADMIN).present?
# Register the scheduled tasks
::ForemanTasks.dynflow.config.on_init(false) do |_world|
ForemanResourceQuota::Engine.register_scheduled_task(
ForemanResourceQuota::Async::RefreshResourceQuotaUtilization,
'0 1 * * *'
)
end
end
rescue ActiveRecord::NoDatabaseError => e
Rails.logger.warn "ForemanResourceQuota: skipping ForemanTasks registration hook (#{e})"
end

initializer 'foreman_resource_quota.register_gettext', after: :load_config_initializers do |_app|
locale_dir = File.join(File.expand_path('../..', __dir__), 'locale')
locale_domain = 'foreman_resource_quota'
Foreman::Gettext::Support.add_text_domain locale_domain, locale_dir
end

# Helper to register ForemanTasks
def self.register_scheduled_task(task_class, cronline)
unless ::ForemanTasks::RecurringLogic.joins(:tasks)
.merge(::ForemanTasks::Task.where(label: task_class.name))
.exists?
::ForemanTasks::RecurringLogic.transaction(isolation: :serializable) do
User.as_anonymous_admin do
recurring_logic = ::ForemanTasks::RecurringLogic.new_from_cronline(cronline)
recurring_logic.save!
recurring_logic.start(task_class)
end
rescue ActiveRecord::TransactionIsolationError => e
Rails.logger.warn "ForemanResourceQuota: skipping RecurringLogic registration hook (#{e})"
end
end
end
end
end

0 comments on commit 4885f93

Please sign in to comment.