From 9fd80b795ed099f07d38aa75aa89f3eca4032f11 Mon Sep 17 00:00:00 2001 From: Bastian Schmidt Date: Wed, 13 Nov 2024 14:20:21 +0100 Subject: [PATCH] WiP: Implement resource_quotas_hosts and hosts_resources --- .../host_managed_extensions.rb | 8 +++++--- .../foreman_resource_quota/host_resources.rb | 11 +++++------ .../foreman_resource_quota/resource_quota.rb | 19 +++++++++++-------- .../resource_quota_host.rb | 10 ++++++++++ config/initializers/inflections.rb | 5 +++++ .../20240611142813_create_hosts_resources.rb | 8 +++++++- .../concerns/host_managed_extension_test.rb | 8 +------- 7 files changed, 44 insertions(+), 25 deletions(-) create mode 100644 app/models/foreman_resource_quota/resource_quota_host.rb diff --git a/app/models/concerns/foreman_resource_quota/host_managed_extensions.rb b/app/models/concerns/foreman_resource_quota/host_managed_extensions.rb index ebe4892..3f44236 100644 --- a/app/models/concerns/foreman_resource_quota/host_managed_extensions.rb +++ b/app/models/concerns/foreman_resource_quota/host_managed_extensions.rb @@ -10,13 +10,15 @@ module HostManagedExtensions validate :verify_resource_quota has_one :host_resources, class_name: '::ForemanResourceQuota::HostResources', - inverse_of: :host, foreign_key: :host_id, dependent: :destroy + inverse_of: :host, dependent: :destroy + has_one :resource_quota_host, class_name: '::ForemanResourceQuota::ResourceQuotaHost', + inverse_of: :host, dependent: :destroy has_one :resource_quota, class_name: '::ForemanResourceQuota::ResourceQuota', - through: :host_resources, foreign_key: :resource_quota_id + through: :resource_quota_host scoped_search relation: :resource_quota, on: :name, complete_value: true, rename: :resource_quota # A host shall always have a .host_resources attribute - before_create :build_host_resources, unless: proc { |h| h.host_resources.present? } + before_create :build_host_resources, unless: -> { host_resources.present? } end def verify_resource_quota diff --git a/app/models/foreman_resource_quota/host_resources.rb b/app/models/foreman_resource_quota/host_resources.rb index ab3fb26..c1924df 100644 --- a/app/models/foreman_resource_quota/host_resources.rb +++ b/app/models/foreman_resource_quota/host_resources.rb @@ -4,11 +4,10 @@ module ForemanResourceQuota class HostResources < ApplicationRecord self.table_name = 'hosts_resources' - belongs_to :resource_quota, class_name: 'ResourceQuota' - belongs_to :host, class_name: '::Host::Managed' # , unqiue: true - # // Talk to Manisha regarding mico-service SQL relation - # -> For some reasion, when adding a host like my_quota.hosts << [some_host_a, some_host_b] results in NEW HostResources entries - # -> See the test on the right + # Make this become the relational one again + # Make ResourceQuota.hosts + # AND ResourceQuota.hosts_resources available -> to easily sum the hosts_resources(:disk) for example. + belongs_to :host, class_name: '::Host::Managed', foreign_key: :host_id validates :host, { presence: true, uniqueness: true } def resources @@ -35,7 +34,7 @@ def resources=(val) def missing_resources(only_active_resources: true) empty_resources = [] resources_to_check = [:cpu_cores, :memory_mb, :disk_gb] - resources_to_check = self.resource_quota.active_resources if only_active_resources && self.resource_quota.present? + resources_to_check = host.resource_quota.active_resources if only_active_resources && host.resource_quota.present? resources_to_check.each do |single_resource| empty_resources << single_resource if self.send(single_resource).nil? diff --git a/app/models/foreman_resource_quota/resource_quota.rb b/app/models/foreman_resource_quota/resource_quota.rb index 79f11a3..ea48f51 100644 --- a/app/models/foreman_resource_quota/resource_quota.rb +++ b/app/models/foreman_resource_quota/resource_quota.rb @@ -12,21 +12,28 @@ class ResourceQuota < ApplicationRecord self.table_name = 'resource_quotas' - has_many :hosts_resources, class_name: 'HostResources', inverse_of: :resource_quota + has_many :resource_quota_hosts, class_name: 'ResourceQuotaHost', inverse_of: :resource_quota, dependent: :destroy has_many :resource_quotas_users, class_name: 'ResourceQuotaUser', inverse_of: :resource_quota, dependent: :destroy has_many :resource_quotas_usergroups, class_name: 'ResourceQuotaUsergroup', inverse_of: :resource_quota, dependent: :destroy - has_many :hosts, -> { distinct }, class_name: '::Host::Managed', through: :hosts_resources + has_many :hosts, -> { distinct }, class_name: '::Host::Managed', through: :resource_quota_hosts + scope :hosts_resources, -> { + HostResources.joins(:host).where(hosts: { id: hosts.select(:id) }) + } + # has_many :hosts_resources, through: :hosts, source: :host_resources + # has_many :hosts_resources, class_name: 'HostResources', through: :hosts, inverse_of: :host_resources has_many :users, class_name: '::User', through: :resource_quotas_users has_many :usergroups, class_name: '::Usergroup', through: :resource_quotas_usergroups validates :name, presence: true, uniqueness: true - after_save :save_hosts_resources - scoped_search on: :name, complete_value: true scoped_search on: :id, complete_enabled: false, only_explicit: true, validator: ScopedSearch::Validators::INTEGER + # def hosts_resources + # HostResources.where(host_id: hosts.select(:id)) + # end + def number_of_hosts hosts_resources.size end @@ -159,9 +166,5 @@ def create_hosts_resources_warning(missing_hosts_resources) warn_text << " '#{host_name}': '#{missing_resources}'\n" unless missing_resources.empty? end end - - def save_hosts_resources - hosts_resources.each { |host_resource| host_resource.save if host_resource.changed? } - end end end diff --git a/app/models/foreman_resource_quota/resource_quota_host.rb b/app/models/foreman_resource_quota/resource_quota_host.rb new file mode 100644 index 0000000..f5193ad --- /dev/null +++ b/app/models/foreman_resource_quota/resource_quota_host.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +module ForemanResourceQuota + class ResourceQuotaHost < ApplicationRecord + self.table_name = 'resource_quotas_hosts' + + belongs_to :resource_quota, class_name: 'ResourceQuota', foreign_key: :resource_quota_id + belongs_to :host, class_name: '::Host::Managed', foreign_key: :host_id + end +end diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index 1248200..dbf4924 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -3,4 +3,9 @@ ActiveSupport::Inflector.inflections do |inflect| inflect.irregular 'resource_quota', 'resource_quotas' inflect.irregular 'host_resources', 'hosts_resources' + inflect.singular 'host_resources', 'host_resources' + inflect.plural 'hosts_resources', 'hosts_resources' + inflect.irregular 'resource_quota_host', 'resource_quota_hosts' + inflect.singular 'resource_quota_host', 'resource_quota_host' + inflect.plural 'resource_quota_hosts', 'resource_quota_hosts' end diff --git a/db/migrate/20240611142813_create_hosts_resources.rb b/db/migrate/20240611142813_create_hosts_resources.rb index f30c3dd..0872f2a 100644 --- a/db/migrate/20240611142813_create_hosts_resources.rb +++ b/db/migrate/20240611142813_create_hosts_resources.rb @@ -2,10 +2,16 @@ class CreateHostsResources < ActiveRecord::Migration[6.1] def change create_table :hosts_resources do |t| t.belongs_to :host, index: { unique: true }, foreign_key: true, null: false - t.belongs_to :resource_quota, foreign_key: true, default: nil t.integer :cpu_cores, default: nil t.integer :memory_mb, default: nil t.integer :disk_gb, default: nil + end + end + + def change + create_table :resource_quotas_hosts do |t| + t.belongs_to :host, index: { unique: true }, foreign_key: true, null: false + t.belongs_to :resource_quota, foreign_key: true, null: false t.timestamps end diff --git a/test/models/concerns/host_managed_extension_test.rb b/test/models/concerns/host_managed_extension_test.rb index 4937454..f6aa86a 100644 --- a/test/models/concerns/host_managed_extension_test.rb +++ b/test/models/concerns/host_managed_extension_test.rb @@ -81,15 +81,9 @@ def setup host_b.name => { cpu_cores: 1, memory_mb: 1 }, } require 'byebug'; byebug - // OK so the issue seems to be that by default in a has many_through through relation - it assumes that there is no entry in the intermediate table (host_resources). However, - we want to keep the entry even if there is no relation (if a host is disassociate from - a quota, we want to keep the relation - because otherwise we must re-calculate - the resources.) - -> try to find a fix for this. Maybe define a custom << method which uses existing entries? quota = FactoryBot.create(:resource_quota, cpu_cores: 10, memory_mb: 10) # quota.hosts_resources << [host_a.host_resources, host_b.host_resources] + quota.hosts.add(host_a) quota.hosts.append([host_a, host_b]) assert quota.save