app/models/zone.rb
class Zone < ApplicationRecord
validates_presence_of :name, :description
validates :name, :unique_within_region => true
serialize :settings, Hash
belongs_to :log_file_depot, :class_name => "FileDepot"
has_many :miq_servers
has_many :ext_management_systems
has_many :paused_ext_management_systems, :class_name => 'ExtManagementSystem', :foreign_key => :zone_before_pause_id
has_many :container_managers, :class_name => "ManageIQ::Providers::ContainerManager"
has_many :miq_schedules, :dependent => :destroy
has_many :providers
has_many :miq_queues, :dependent => :delete_all, :foreign_key => :zone, :primary_key => :name
has_many :hosts, :through => :ext_management_systems
has_many :clustered_hosts, :through => :ext_management_systems
has_many :non_clustered_hosts, :through => :ext_management_systems
has_many :vms_and_templates, :through => :ext_management_systems
has_many :vms, :through => :ext_management_systems
has_many :miq_templates, :through => :ext_management_systems
has_many :ems_clusters, :through => :ext_management_systems
has_many :physical_servers, :through => :ext_management_systems
has_many :storages, :through => :ext_management_systems
has_many :container_nodes, :through => :container_managers
has_many :container_groups, :through => :container_managers
has_many :container_replicators, :through => :container_managers
has_many :containers, :through => :container_managers
has_many :host_hardwares, :class_name => 'Hardware', :through => :hosts, :source => :hardware
has_many :vm_hardwares, :class_name => 'Hardware', :through => :vms_and_templates, :source => :hardware
virtual_has_many :active_miq_servers, :class_name => "MiqServer"
before_destroy :remove_servers_if_podified
before_destroy :check_zone_in_use_on_destroy
after_create :create_server_if_podified
include AuthenticationMixin
include SupportsFeatureMixin
include Metric::CiMixin
include AggregationMixin
include ConfigurationManagementMixin
scope :visible, -> { where(:visible => true) }
default_value_for :visible, true
def active_miq_servers
MiqServer.active_miq_servers.where(:zone_id => id)
end
def servers_for_settings_reload
miq_servers.where(:status => "started")
end
def find_master_server
active_miq_servers.detect(&:is_master?)
end
def self.create_maintenance_zone
return MiqRegion.my_region.maintenance_zone if MiqRegion.my_region.maintenance_zone.present?
begin
# 1) Create Maintenance zone
zone = create!(:name => "__maintenance__#{SecureRandom.uuid}",
:description => "Maintenance Zone",
:visible => false)
# 2) Assign to MiqRegion
MiqRegion.my_region.update(:maintenance_zone => zone)
rescue ActiveRecord::RecordInvalid
raise if zone.errors[:name].blank?
retry
end
_log.info("Creating maintenance zone...")
zone
end
private_class_method :create_maintenance_zone
def self.seed
MiqRegion.seed
create_maintenance_zone
create_with(:description => "Default Zone").find_or_create_by!(:name => 'default') do |_z|
_log.info("Creating default zone...")
end
end
def miq_region
MiqRegion.find_by(:region => region_id)
end
def assigned_roles
miq_servers.flat_map(&:assigned_roles).uniq.compact
end
def role_active?(role_name)
active_miq_servers.any? { |s| s.has_active_role?(role_name) }
end
def role_assigned?(role_name)
active_miq_servers.any? { |s| s.has_assigned_role?(role_name) }
end
def active_role_names
miq_servers.flat_map(&:active_role_names).uniq
end
def maintenance?
self.class.maintenance?(self)
end
def self.default_zone
in_my_region.find_by(:name => "default")
end
def self.with_active_role(role_name)
select { |z| z.role_active?(role_name) }
end
# Zone for paused providers (no servers in it), not visible by default
def self.maintenance_zone
MiqRegion.my_region&.maintenance_zone
end
def self.maintenance?(zone)
case zone
when NilClass then false
when String then maintenance_zone&.name == zone
else maintenance_zone == zone
end
end
# The zone to use when inserting a record into MiqQueue
def self.determine_queue_zone(options)
if options.key?(:zone)
options[:zone] # return specified zone including nil (aka ANY zone)
elsif options[:role] && ServerRole.regional_role?(options[:role])
nil # ANY zone, will be limited by role
else
MiqServer.my_zone
end
end
def synchronize_logs(*args)
options = args.extract_options!
enabled = Settings.log.collection.include_automate_models_and_dialogs
active_miq_servers.each_with_index do |s, index|
# If enabled, export the automate domains and dialogs on the first active server
include_models_and_dialogs = enabled ? index.zero? : false
s.synchronize_logs(*args, options.merge(:include_automate_models_and_dialogs => include_models_and_dialogs))
end
end
def last_log_sync_on
miq_servers.inject(nil) do |d, s|
last = s.last_log_sync_on
d ||= last
d = last if last && last > d
d
end
end
def log_collection_active?
miq_servers.any?(&:log_collection_active?)
end
def log_collection_active_recently?(since = nil)
miq_servers.any? { |s| s.log_collection_active_recently?(since) }
end
def self.hosts_without_a_zone
Host.where(:ems_id => nil).to_a
end
def self.clusters_without_a_zone
EmsCluster.where(:ems_id => nil).to_a
end
def ems_infras
ext_management_systems.select { |e| e.kind_of?(EmsInfra) }
end
def ems_containers
ext_management_systems.select { |e| e.kind_of?(ManageIQ::Providers::ContainerManager) }
end
def ems_datawarehouses
ext_management_systems.select { |e| e.kind_of?(ManageIQ::Providers::DatawarehouseManager) }
end
def ems_monitors
ext_management_systems.select { |e| e.kind_of?(ManageIQ::Providers::MonitoringManager) }
end
def ems_configproviders
ext_management_systems.select { |e| e.kind_of?(ManageIQ::Providers::ConfigurationManager) }
end
def ems_clouds
ext_management_systems.select { |e| e.kind_of?(EmsCloud) }
end
# @return [Array<ExtManagementSystem>] All emses that can collect Capacity and Utilization metrics
def ems_metrics_collectable
ext_management_systems.supporting(:metrics)
end
def ems_networks
ext_management_systems.select { |e| e.kind_of?(ManageIQ::Providers::NetworkManager) }
end
def availability_zones
MiqPreloader.preload(ems_clouds, :availability_zones)
ems_clouds.flat_map(&:availability_zones)
end
def self.vms_without_a_zone
Vm.where(:ems_id => nil).to_a
end
def self.storages_without_a_zone
storage_without_hosts = Storage.includes(:hosts).where(:host_storages => {:storage_id => nil}).to_a
storage_without_ems = Host.where(:ems_id => nil).includes(:storages).flat_map(&:storages).uniq
storage_without_hosts + storage_without_ems
end
def display_name
name
end
def active?
miq_servers.any?(&:active?)
end
def any_started_miq_servers?
miq_servers.any?(&:started?)
end
def message_for_invalid_delete
return _("cannot delete default zone") if name == "default"
return _("cannot delete maintenance zone") if maintenance?
return _("zone name '%{name}' is used by a server") % {:name => name} if !MiqEnvironment::Command.is_podified? && miq_servers.present?
_("zone name '%{name}' is used by a provider") % {:name => name} if ext_management_systems.present?
end
protected
def remove_servers_if_podified
return unless MiqEnvironment::Command.is_podified?
miq_servers.destroy_all
end
def create_server_if_podified
return unless MiqEnvironment::Command.is_podified?
return if name == "default" || !visible
miq_servers.create!(:name => name)
end
def check_zone_in_use_on_destroy
msg = message_for_invalid_delete
raise msg if msg
end
end