diff --git a/app/models/container_project.rb b/app/models/container_project.rb index ab5016ff882d..cac98789cefe 100644 --- a/app/models/container_project.rb +++ b/app/models/container_project.rb @@ -5,6 +5,7 @@ class ContainerProject < ApplicationRecord include MiqPolicyMixin include TenantIdentityMixin include CustomActionsMixin + include AggregationMixin include_concern 'Purging' belongs_to :ext_management_system, :foreign_key => "ems_id" has_many :container_groups, -> { active } @@ -44,7 +45,6 @@ class ContainerProject < ApplicationRecord include EventMixin include Metric::CiMixin - include AggregationMixin::Methods PERF_ROLLUP_CHILDREN = :all_container_groups diff --git a/app/models/ems_cluster.rb b/app/models/ems_cluster.rb index e67d62972967..56ef16192181 100644 --- a/app/models/ems_cluster.rb +++ b/app/models/ems_cluster.rb @@ -36,6 +36,9 @@ class EmsCluster < ApplicationRecord virtual_has_many :resource_pools, :uses => :all_relationships virtual_has_many :lans, :uses => {:hosts => :lans} + has_many :host_hardwares, :class_name => 'Hardware', :through => :hosts, :source => :hardware + has_many :vm_hardwares, :class_name => 'Hardware', :through => :vms_and_templates, :source => :hardware + has_many :failover_hosts, -> { failover }, :class_name => "Host" delegate :queue_name_for_ems_operations, :to => :ext_management_system, :allow_nil => true @@ -107,6 +110,14 @@ def total_vcpus # Relationship methods # + def all_storages + hosts.collect(&:storages).flatten.compact.uniq + end + + def lans + hosts.flat_map(&:lans).compact.uniq + end + alias_method :storages, :all_storages alias_method :datastores, :all_storages # Used by web-services to return datastores as the property name diff --git a/app/models/ext_management_system.rb b/app/models/ext_management_system.rb index 4643cb2870e0..39e68f83f127 100644 --- a/app/models/ext_management_system.rb +++ b/app/models/ext_management_system.rb @@ -183,6 +183,9 @@ def validate_zone_not_maintenance_when_ems_enabled? include AggregationMixin + has_many :host_hardwares, :class_name => 'Hardware', :through => :hosts, :source => :hardware + has_many :vm_hardwares, :class_name => 'Hardware', :through => :vms_and_templates, :source => :hardware + include AuthenticationMixin include Metric::CiMixin include AsyncDeleteMixin diff --git a/app/models/host.rb b/app/models/host.rb index 98b1725c1dfd..919ed8a37029 100644 --- a/app/models/host.rb +++ b/app/models/host.rb @@ -146,6 +146,10 @@ class Host < ApplicationRecord virtual_total :v_total_vms, :vms virtual_total :v_total_miq_templates, :miq_templates + has_many :host_hardwares, :class_name => 'Hardware', :source => :hardware + has_many :vm_hardwares, :class_name => 'Hardware', :through => :vms_and_templates, :source => :hardware + include AggregationMixin + scope :active, -> { where.not(:ems_id => nil) } scope :archived, -> { where(:ems_id => nil) } diff --git a/app/models/miq_region.rb b/app/models/miq_region.rb index c836460c6805..6c7f22010de2 100644 --- a/app/models/miq_region.rb +++ b/app/models/miq_region.rb @@ -19,6 +19,10 @@ class MiqRegion < ApplicationRecord virtual_has_many :miq_templates virtual_has_many :vms + virtual_aggregate :aggregate_physical_cpus, :host_hardwares, :sum, :cpu_sockets + has_many :host_hardwares, :class_name => 'Hardware', :through => :hosts, :source => :hardware + has_many :vm_hardwares, :class_name => 'Hardware', :through => :vms_and_templates, :source => :hardware + after_save :clear_my_region_cache acts_as_miq_taggable diff --git a/app/models/miq_server.rb b/app/models/miq_server.rb index f0069998226c..c5551819d71d 100644 --- a/app/models/miq_server.rb +++ b/app/models/miq_server.rb @@ -491,7 +491,7 @@ def self.managed_resources { :vms => Vm.active.count, :hosts => Host.active.count, - :aggregate_physical_cpus => MiqRegion.my_region.aggregate_physical_cpus(Host.active), + :aggregate_physical_cpus => Host.active.first.aggregate_physical_cpus, } end @@ -499,7 +499,7 @@ def self.unmanaged_resources { :vms => Vm.not_active.count, :hosts => Host.archived.count, - :aggregate_physical_cpus => MiqRegion.my_region.aggregate_physical_cpus(Host.archived), + :aggregate_physical_cpus => Host.archived.first.aggregate_physical_cpus, } end diff --git a/app/models/mixins/aggregation_mixin.rb b/app/models/mixins/aggregation_mixin.rb index e5e5749578dc..09971d62eb00 100644 --- a/app/models/mixins/aggregation_mixin.rb +++ b/app/models/mixins/aggregation_mixin.rb @@ -1,13 +1,13 @@ module AggregationMixin extend ActiveSupport::Concern included do - virtual_column :aggregate_cpu_speed, :type => :integer, :uses => :hosts - virtual_column :aggregate_cpu_total_cores, :type => :integer, :uses => :hosts - virtual_column :aggregate_physical_cpus, :type => :integer, :uses => :hosts - virtual_column :aggregate_memory, :type => :integer, :uses => :hosts - virtual_column :aggregate_vm_cpus, :type => :integer, :uses => :vms_and_templates - virtual_column :aggregate_vm_memory, :type => :integer, :uses => :vms_and_templates - virtual_column :aggregate_disk_capacity, :type => :integer, :uses => :hosts + virtual_aggregate :aggregate_vm_memory, :vm_hardwares, :sum, :memory_mb + virtual_aggregate :aggregate_vm_cpus, :vm_hardwares, :sum, :cpu_sockets + virtual_aggregate :aggregate_physical_cpus, :host_hardwares, :sum, :cpu_sockets + virtual_aggregate :aggregate_disk_capacity, :host_hardwares, :sum, :disk_capacity + virtual_aggregate :aggregate_memory, :host_hardwares, :sum, :memory_mb + virtual_aggregate :aggregate_cpu_total_cores, :host_hardwares, :sum, :cpu_total_cores + virtual_aggregate :aggregate_cpu_speed, :host_hardwares, :sum, :aggregate_cpu_speed alias_method :all_hosts, :hosts alias_method :all_host_ids, :host_ids @@ -17,7 +17,14 @@ module AggregationMixin alias_method :all_vm_ids, :vm_ids alias_method :all_miq_templates, :miq_templates alias_method :all_miq_template_ids, :miq_template_ids + def aggregate_hardware(from, field, targets = nil) + from = from.to_s.singularize + select = field == :aggregate_cpu_speed ? "cpu_total_cores, cpu_speed" : field + targets ||= send("all_#{from}_ids") + targets = targets.collect(&:id) unless targets.first.kind_of?(Integer) + hdws = Hardware.where("#{from}_id".to_sym => targets).select(select) - include AggregationMixin::Methods + hdws.inject(0) { |t, hdw| t + hdw.send(field).to_i } + end end end diff --git a/app/models/mixins/aggregation_mixin/methods.rb b/app/models/mixins/aggregation_mixin/methods.rb deleted file mode 100644 index 866f2025ffc8..000000000000 --- a/app/models/mixins/aggregation_mixin/methods.rb +++ /dev/null @@ -1,57 +0,0 @@ -module AggregationMixin - module Methods - extend ActiveSupport::Concern - - def aggregate_cpu_speed(targets = nil) - aggregate_hardware(:hosts, :aggregate_cpu_speed, targets) - end - - def aggregate_cpu_total_cores(targets = nil) - aggregate_hardware(:hosts, :cpu_total_cores, targets) - end - - def aggregate_physical_cpus(targets = nil) - aggregate_hardware(:hosts, :cpu_sockets, targets) - end - - def aggregate_memory(targets = nil) - aggregate_hardware(:hosts, :memory_mb, targets) - end - - def aggregate_vm_cpus(targets = nil) - aggregate_hardware(:vms_and_templates, :cpu_sockets, targets) - end - - def aggregate_vm_memory(targets = nil) - aggregate_hardware(:vms_and_templates, :memory_mb, targets) - end - - def aggregate_disk_capacity(targets = nil) - aggregate_hardware(:hosts, :disk_capacity, targets) - end - - # Default implementations which can be overridden with something more optimized - - def all_storages - hosts = all_hosts - MiqPreloader.preload(hosts, :storages) - hosts.collect(&:storages).flatten.compact.uniq - end - - def aggregate_hardware(from, field, targets = nil) - from = from.to_s.singularize - select = field == :aggregate_cpu_speed ? "cpu_total_cores, cpu_speed" : field - targets ||= send("all_#{from}_ids") - targets = targets.collect(&:id) unless targets.first.kind_of?(Integer) - hdws = Hardware.where("#{from}_id".to_sym => targets).select(select) - - hdws.inject(0) { |t, hdw| t + hdw.send(field).to_i } - end - - def lans - hosts = all_hosts - MiqPreloader.preload(hosts, :lans) - hosts.flat_map(&:lans).compact.uniq - end - end -end diff --git a/app/models/mixins/relationships_aggregation_mixin.rb b/app/models/mixins/relationships_aggregation_mixin.rb index e03dde1215b8..601f0bf6d889 100644 --- a/app/models/mixins/relationships_aggregation_mixin.rb +++ b/app/models/mixins/relationships_aggregation_mixin.rb @@ -8,8 +8,6 @@ module RelationshipsAggregationMixin virtual_column :aggregate_vm_cpus, :type => :integer, :uses => :all_relationships virtual_column :aggregate_vm_memory, :type => :integer, :uses => :all_relationships virtual_column :aggregate_disk_capacity, :type => :integer, :uses => :all_relationships - - include AggregationMixin::Methods end # Default implementations which can be overridden with something more optimized diff --git a/spec/models/ems_cluster_spec.rb b/spec/models/ems_cluster_spec.rb index 22ee9d38d058..e29cec7313b7 100644 --- a/spec/models/ems_cluster_spec.rb +++ b/spec/models/ems_cluster_spec.rb @@ -114,28 +114,53 @@ it('#total_hosts') { expect(@cluster.total_hosts).to eq(2) } end - it "#save_drift_state" do - # TODO: Beef up with more data - cluster = FactoryBot.create(:ems_cluster) - cluster.save_drift_state - - expect(cluster.drift_states.size).to eq(1) - expect(DriftState.count).to eq(1) - - expect(cluster.drift_states.first.data).to eq({ - :aggregate_cpu_speed => 0, - :aggregate_cpu_total_cores => 0, - :aggregate_memory => 0, - :aggregate_physical_cpus => 0, - :aggregate_vm_cpus => 0, - :aggregate_vm_memory => 0, - :class => "EmsCluster", - :id => cluster.id, - :name => cluster.name, - :vms => [], - :miq_templates => [], - :hosts => [], - }) + context("#save_drift_state") do + it "without aggregate data" do + # TODO: Beef up with more data + cluster = FactoryBot.create(:ems_cluster) + cluster.save_drift_state + + expect(cluster.drift_states.size).to eq(1) + expect(DriftState.count).to eq(1) + + expect(cluster.drift_states.first.data).to eq( + :class => "EmsCluster", + :id => cluster.id, + :name => cluster.name, + :vms => [], + :miq_templates => [], + :hosts => [] + ) + end + + it "with aggregate data" do + cluster = FactoryBot.create(:ems_cluster) + host = FactoryBot.create(:host, + :ems_cluster => cluster, + :ext_management_system => FactoryBot.create(:ext_management_system), + :hardware => FactoryBot.build(:hardware, + :cpu_total_cores => 4, + :cpu_speed => 1000)) + + vm = FactoryBot.create(:vm_redhat, :host => host, :ems_cluster => cluster) + + cluster.save_drift_state + + expect(cluster.drift_states.size).to eq(1) + expect(DriftState.count).to eq(1) + expect(cluster.drift_states.first.data).to eq( + :aggregate_cpu_speed => 4000, + :aggregate_cpu_total_cores => 4, + :aggregate_memory => 0, + :aggregate_physical_cpus => 1, + :class => "EmsCluster", + :id => cluster.id, + :name => cluster.name, + :vms => [{:class => "ManageIQ::Providers::Redhat::InfraManager::Vm", :id => vm.id}], + :miq_templates => [], + :hosts => [{:class => "Host", :id => host.id}] + ) + end end context("#perf_capture_enabled_host_ids=") do diff --git a/spec/models/ext_management_system_spec.rb b/spec/models/ext_management_system_spec.rb index 94e23f8b342d..c805606ca628 100644 --- a/spec/models/ext_management_system_spec.rb +++ b/spec/models/ext_management_system_spec.rb @@ -353,18 +353,59 @@ @ems = FactoryBot.create(:ems_vmware) 2.times do FactoryBot.create(:vm_vmware, - :ext_management_system => @ems, - :hardware => FactoryBot.create(:hardware, - :cpu1x2, - :ram1GB)) + :ext_management_system => @ems, + :hardware => FactoryBot.create(:hardware, + :cpu1x2, + :ram1GB)) end 2.times do FactoryBot.create(:host, - :ext_management_system => @ems, - :hardware => FactoryBot.create(:hardware, - :cpu2x2, - :ram1GB)) + :ext_management_system => @ems, + :hardware => FactoryBot.create(:hardware, + :cpu2x2, + :ram1GB)) end + 2.times do + FactoryBot.create(:host, + :ext_management_system => @ems, + :hardware => FactoryBot.build(:hardware, + :cpu_total_cores => 4, + :cpu_speed => 1000)) + end + 2.times do + FactoryBot.create(:host, + :ext_management_system => @ems, + :hardware => FactoryBot.create(:hardware, + :disk_capacity => 300)) + end + end + + it "#aggregate_vm_memory" do + expect(@ems.aggregate_vm_memory).to eq(2048) + end + + it "#aggregate_vm_cpus" do + expect(@ems.aggregate_vm_cpus).to eq(2) + end + + it "#aggregate_physical_cpus" do + expect(@ems.aggregate_physical_cpus).to eq(8) + end + + it "#aggregate_disk_capacity" do + expect(@ems.aggregate_disk_capacity).to eq(0.6e3) + end + + it "#aggregate_memory" do + expect(@ems.aggregate_memory).to eq(2048) + end + + it "#aggregate_cpu_total_cores" do + expect(@ems.aggregate_cpu_total_cores).to eq(16) + end + + it "#aggregate_cpu_speed" do + expect(@ems.aggregate_cpu_speed).to eq(8000) end it "#total_cloud_vcpus" do @@ -376,7 +417,7 @@ end it "#total_vcpus" do - expect(@ems.total_vcpus).to eq(8) + expect(@ems.total_vcpus).to eq(16) end it "#total_memory" do diff --git a/spec/models/mixins/aggregation_mixin_spec.rb b/spec/models/mixins/aggregation_mixin_spec.rb index d56125b8d69e..0c2b61589fae 100644 --- a/spec/models/mixins/aggregation_mixin_spec.rb +++ b/spec/models/mixins/aggregation_mixin_spec.rb @@ -22,7 +22,12 @@ it "calculates from objects" do cluster = cluster_2_1_host(hardware_args) partial_cluster = cluster.hosts[1..1] + cluster.hosts[2..2] - expect(cluster.aggregate_cpu_speed(partial_cluster)).to eq(cpu_speed) + + MiqPreloader.preload(partial_cluster, :aggregate_cpu_speed) + expect { + expect(partial_cluster.first.aggregate_cpu_speed).to eq(cpu_speed) + expect(partial_cluster.last.aggregate_cpu_speed).to eq(0) + }.to match_query_limit_of(0) end it "calculates from ids" do @@ -42,7 +47,12 @@ it "calculates from objects" do cluster = cluster_2_1_host(hardware_args) partial_cluster = cluster.hosts[1..1] + cluster.hosts[2..2] - expect(cluster.aggregate_cpu_total_cores(partial_cluster)).to eq(8) + + MiqPreloader.preload(partial_cluster, :aggregate_cpu_speed) + expect { + expect(partial_cluster.first.aggregate_cpu_total_cores).to eq(8) + expect(partial_cluster.last.aggregate_cpu_total_cores).to eq(0) + }.to match_query_limit_of(0) end it "calculates from ids" do @@ -69,7 +79,12 @@ it "calculates from objects" do cluster = cluster_2_1_host(hardware_args) partial_cluster = cluster.hosts[1..1] + cluster.hosts[2..2] - expect(cluster.aggregate_memory(partial_cluster)).to eq(memory) + + MiqPreloader.preload(partial_cluster, :aggregate_memory) + expect { + expect(partial_cluster.first.aggregate_memory).to eq(memory) + expect(partial_cluster.last.aggregate_memory).to eq(0) + }.to match_query_limit_of(0) end it "calculates from ids" do @@ -102,7 +117,8 @@ it "calculates from vms" do cluster = cluster_2_1_host(hardware_args) partial_cluster = cluster.hosts[1..1] + cluster.hosts[2..2] - expect(cluster.aggregate_disk_capacity(partial_cluster)).to eq(40) + expect(partial_cluster.first.aggregate_disk_capacity).to eq(40) + expect(partial_cluster.last.aggregate_disk_capacity).to eq(0.0) end it "calculates from vm ids" do