diff --git a/app/models/manageiq/providers/base_manager/metrics_capture.rb b/app/models/manageiq/providers/base_manager/metrics_capture.rb index ce4473d25d4..003c992a50b 100644 --- a/app/models/manageiq/providers/base_manager/metrics_capture.rb +++ b/app/models/manageiq/providers/base_manager/metrics_capture.rb @@ -80,7 +80,7 @@ def filter_perf_capture_now(targets, target_options) end def capture_ems_targets(options = {}) - Metric::Targets.capture_ems_targets(ems, options) + raise(NotImplementedError, _("must be implemented in subclass")) end # if it has not been run, or it was a very long time ago, just run it diff --git a/app/models/manageiq/providers/infra_manager.rb b/app/models/manageiq/providers/infra_manager.rb index 8a29fa6c262..f1756bb9daf 100644 --- a/app/models/manageiq/providers/infra_manager.rb +++ b/app/models/manageiq/providers/infra_manager.rb @@ -3,6 +3,7 @@ class InfraManager < BaseManager require_nested :Cluster require_nested :Datacenter require_nested :Folder + require_nested :MetricsCapture require_nested :ProvisionWorkflow require_nested :ResourcePool require_nested :Storage diff --git a/app/models/manageiq/providers/infra_manager/metrics_capture.rb b/app/models/manageiq/providers/infra_manager/metrics_capture.rb index df81a47e1e8..6fccd3f77b5 100644 --- a/app/models/manageiq/providers/infra_manager/metrics_capture.rb +++ b/app/models/manageiq/providers/infra_manager/metrics_capture.rb @@ -1,5 +1,100 @@ class ManageIQ::Providers::InfraManager::MetricsCapture < ManageIQ::Providers::BaseManager::MetricsCapture def capture_ems_targets(options = {}) - Metric::Targets.capture_infra_targets([ems], options) + capture_infra_targets([ems], options) + end + + private + + # If a Cluster, standalone Host, or Storage is not enabled, skip it. + # If a Cluster is enabled, capture all of its Hosts. + # If a Host is enabled, capture all of its Vms. + def capture_infra_targets(emses, options) + load_infra_targets_data(emses, options) + all_hosts = capture_host_targets(emses) + targets = enabled_hosts = only_enabled(all_hosts) + targets += capture_storage_targets(all_hosts) unless options[:exclude_storages] + targets += capture_vm_targets(emses, enabled_hosts) + + targets + end + + # Filter to enabled hosts. If it has a cluster consult that, otherwise consult the host itself. + # + # NOTE: if capture_storage takes only enabled, then move + # this logic into capture_host_targets + def only_enabled(hosts) + hosts.select do |host| + host.supports_capture? && (host.ems_cluster ? host.ems_cluster.perf_capture_enabled? : host.perf_capture_enabled?) + end + end + + # preload emses with relations that will be used in cap&u + # + # tags are needed for determining if it is enabled. + # ems is needed for determining queue name + # cluster is used for hierarchies + def load_infra_targets_data(emses, options) + MiqPreloader.preload(emses, preload_hash_infra_targets_data(options)) + postload_infra_targets_data(emses, options) + end + + def preload_hash_infra_targets_data(options) + # Preload all of the objects we are going to be inspecting. + includes = {:hosts => {:ems_cluster => :tags, :tags => {}}} + includes[:hosts][:storages] = :tags unless options[:exclude_storages] + includes[:vms] = {} + includes + end + + # populate parts of the hierarchy that are not properly preloaded + # + # inverse_of does not work with :through. + # e.g.: :ems => :hosts => vms will not preload vms.ems + # + # adding in a preload for vms => :ems will fix, but different objects get assigned + # and since we also rely upon tags and clusters, this causes unnecessary data to be downloaded + # + # so we have introduced this to work around preload not working (and inverse_of) + def postload_infra_targets_data(emses, options) + # populate ems (with tags / clusters) + emses.each do |ems| + ems.hosts.each do |host| + host.ems_cluster.association(:ext_management_system).target = ems if host.ems_cluster_id + unless options[:exclude_storages] + host.storages.each do |storage| + storage.ext_management_system = ems + end + end + end + host_ids = ems.hosts.index_by(&:id) + clusters = ems.hosts.flat_map(&:ems_cluster).uniq.compact.index_by(&:id) + ems.vms.each do |vm| + vm.association(:ext_management_system).target = ems if vm.ems_id + vm.association(:ems_cluster).target = clusters[vm.ems_cluster_id] if vm.ems_cluster_id + vm.association(:host).target = host_ids[vm.host_id] if vm.host_id + end + end + end + + def capture_host_targets(emses) + # NOTE: if capture_storage_targets takes only enabled hosts + # merge only_enabled into this method + emses.flat_map(&:hosts) + end + + # @param [Host] all hosts that have an ems + # NOTE: disabled hosts are passed in. + # @return [Array] supported storages + # hosts preloaded storages and tags + def capture_storage_targets(hosts) + hosts.flat_map(&:storages).uniq.select { |s| Storage.supports?(s.store_type) & s.perf_capture_enabled? } + end + + # @param [Array] emses Typically 1 ems for this zone + # @param [Host] hosts that are enabled or cluster enabled + # we want to work with only enabled_hosts, so hosts needs to be further filtered + def capture_vm_targets(emses, hosts) + enabled_host_ids = hosts.select(&:perf_capture_enabled?).index_by(&:id) + emses.flat_map { |e| e.vms.select { |v| enabled_host_ids.key?(v.host_id) && v.state == 'on' && v.supports_capture? } } end end diff --git a/app/models/metric/targets.rb b/app/models/metric/targets.rb index 6dabd640cbb..d6dbc140639 100644 --- a/app/models/metric/targets.rb +++ b/app/models/metric/targets.rb @@ -12,103 +12,4 @@ def self.targets_archived_from archived_for_setting = Settings.performance.targets.archived_for archived_for_setting.to_i_with_method.seconds.ago.utc end - - def self.capture_ems_targets(ems, options = {}) - case ems - when EmsInfra then capture_infra_targets([ems], options) - end - end - - # If a Cluster, standalone Host, or Storage is not enabled, skip it. - # If a Cluster is enabled, capture all of its Hosts. - # If a Host is enabled, capture all of its Vms. - def self.capture_infra_targets(emses, options) - load_infra_targets_data(emses, options) - all_hosts = capture_host_targets(emses) - targets = enabled_hosts = only_enabled(all_hosts) - targets += capture_storage_targets(all_hosts) unless options[:exclude_storages] - targets += capture_vm_targets(emses, enabled_hosts) - - targets - end - - # Filter to enabled hosts. If it has a cluster consult that, otherwise consult the host itself. - # - # NOTE: if capture_storage takes only enabled, then move - # this logic into capture_host_targets - def self.only_enabled(hosts) - hosts.select do |host| - host.supports_capture? && (host.ems_cluster ? host.ems_cluster.perf_capture_enabled? : host.perf_capture_enabled?) - end - end - - # preload emses with relations that will be used in cap&u - # - # tags are needed for determining if it is enabled. - # ems is needed for determining queue name - # cluster is used for hierarchies - def self.load_infra_targets_data(emses, options) - MiqPreloader.preload(emses, preload_hash_infra_targets_data(options)) - postload_infra_targets_data(emses, options) - end - - def self.preload_hash_infra_targets_data(options) - # Preload all of the objects we are going to be inspecting. - includes = {:hosts => {:ems_cluster => :tags, :tags => {}}} - includes[:hosts][:storages] = :tags unless options[:exclude_storages] - includes[:vms] = {} - includes - end - - # populate parts of the hierarchy that are not properly preloaded - # - # inverse_of does not work with :through. - # e.g.: :ems => :hosts => vms will not preload vms.ems - # - # adding in a preload for vms => :ems will fix, but different objects get assigned - # and since we also rely upon tags and clusters, this causes unnecessary data to be downloaded - # - # so we have introduced this to work around preload not working (and inverse_of) - def self.postload_infra_targets_data(emses, options) - # populate ems (with tags / clusters) - emses.each do |ems| - ems.hosts.each do |host| - host.ems_cluster.association(:ext_management_system).target = ems if host.ems_cluster_id - unless options[:exclude_storages] - host.storages.each do |storage| - storage.ext_management_system = ems - end - end - end - host_ids = ems.hosts.index_by(&:id) - clusters = ems.hosts.flat_map(&:ems_cluster).uniq.compact.index_by(&:id) - ems.vms.each do |vm| - vm.association(:ext_management_system).target = ems if vm.ems_id - vm.association(:ems_cluster).target = clusters[vm.ems_cluster_id] if vm.ems_cluster_id - vm.association(:host).target = host_ids[vm.host_id] if vm.host_id - end - end - end - - def self.capture_host_targets(emses) - # NOTE: if capture_storage_targets takes only enabled hosts - # merge only_enabled into this method - emses.flat_map(&:hosts) - end - - # @param [Host] all hosts that have an ems - # NOTE: disabled hosts are passed in. - # @return [Array] supported storages - # hosts preloaded storages and tags - def self.capture_storage_targets(hosts) - hosts.flat_map(&:storages).uniq.select { |s| Storage.supports?(s.store_type) & s.perf_capture_enabled? } - end - - # @param [Array] emses Typically 1 ems for this zone - # @param [Host] hosts that are enabled or cluster enabled - # we want to work with only enabled_hosts, so hosts needs to be further filtered - def self.capture_vm_targets(emses, hosts) - enabled_host_ids = hosts.select(&:perf_capture_enabled?).index_by(&:id) - emses.flat_map { |e| e.vms.select { |v| enabled_host_ids.key?(v.host_id) && v.state == 'on' && v.supports_capture? } } - end end