# frozen_string_literal: true module ForemanResourceQuota module ResourceQuotaHelper FACTOR_B_TO_KB = 1024 FACTOR_B_TO_MB = 1024 * 1024 FACTOR_B_TO_GB = 1024 * FACTOR_B_TO_MB def natural_resource_name_by_type(resource_type) type_names = { cpu_cores: 'CPU cores', memory_mb: 'Memory', disk_gb: 'Disk space' } key = resource_type.is_a?(String) ? resource_type.to_sym : resource_type raise "No natural name for unknown resource type '#{resource_type}'" unless type_names.key?(key) type_names[key] end def units_by_type(resource_type) type_units = { cpu_cores: [ { symbol: 'cores', factor: 1 }, ], memory_mb: [ { symbol: 'MB', factor: 1 }, { symbol: 'GB', factor: FACTOR_B_TO_KB }, { symbol: 'TB', factor: FACTOR_B_TO_MB }, ], disk_gb: [ { symbol: 'GB', factor: 1 }, { symbol: 'TB', factor: FACTOR_B_TO_KB }, { symbol: 'PB', factor: FACTOR_B_TO_MB }, ], } key = resource_type.to_sym raise "No units for unknown resource type '#{resource_type}'" unless type_units.key?(key) type_units[key] end def find_largest_unit(resource_value, units) units.reverse_each do |unit| return unit.values_at(:symbol, :factor) if resource_value >= unit[:factor] end units[0].values_at(:symbol, :factor) end def resource_value_to_string(resource_value, resource_type) (symbol, factor) = find_largest_unit(resource_value, units_by_type(resource_type)) unit_applied_value = (resource_value / factor).round(1) format_text = if (unit_applied_value % 1).zero? '%.0f %s' else '%.1f %s' end format(format_text, unit_applied_value, symbol) end def utilization_from_resource_origins(resources, hosts, custom_resource_origins: nil) utilization_sum = resources.each.with_object({}) { |key, hash| hash[key] = 0 } missing_hosts_resources = create_missing_hosts_resources_hash(hosts, resources) hosts_hash = hosts.index_by(&:name) resource_classes = custom_resource_origins || default_resource_origin_classes resource_classes.each do |origin_class| origin_class.new.collect_resources!( utilization_sum, missing_hosts_resources, hosts_hash ) end [utilization_sum, missing_hosts_resources] end private # Create a Hash that maps resources to host names. # { : [] } # for example: # { # "host_a": { # [ :cpu_cores, :disk_gb ] # }, # "host_b": { # [ :cpu_cores, :disk_gb ] # }, # Parameters: # - hosts: Array of host objects. # - resources: Array of resources (as symbol, e.g. [:cpu_cores, :disk_gb]). # Returns: Hash with host names as keys and resources as values. def create_missing_hosts_resources_hash(hosts, resources) return {} if hosts.empty? || resources.empty? resources_to_determine = resources.compact return {} if resources_to_determine.empty? hosts.map(&:name).index_with { resources_to_determine.clone } end # Default classes that are used to determine host resources. Determines # resources in the order of this list. def default_resource_origin_classes [ ResourceOrigins::ComputeResourceOrigin, ResourceOrigins::VMAttributesOrigin, ResourceOrigins::ComputeAttributesOrigin, ResourceOrigins::FactsOrigin, ] end end end