foreman/app/models/host/managed.rb @ bb3572ff
d7611b24 | Greg Sutcliffe | class Host::Managed < Host::Base
|
|
include ReportCommon
|
|||
feacea35 | Amos Benari | include Hostext::Search
|
|
3d03e334 | Dominic Cleal | PROVISION_METHODS = %w[build image]
|
|
83683ed0 | Tomer Brisker | has_many :host_classes, :foreign_key => :host_id
|
|
has_many :puppetclasses, :through => :host_classes, :dependent => :destroy
|
|||
d7611b24 | Greg Sutcliffe | belongs_to :hostgroup
|
|
3e750719 | Daniel Lobato | has_many :reports, :foreign_key => :host_id
|
|
998e1438 | Ori Rabin | has_many :host_parameters, :dependent => :destroy, :foreign_key => :reference_id, :inverse_of => :host
|
|
d7611b24 | Greg Sutcliffe | has_many :parameters, :dependent => :destroy, :foreign_key => :reference_id, :class_name => "HostParameter"
|
|
32ced385 | Ori Rabin | accepts_nested_attributes_for :host_parameters, :allow_destroy => true
|
|
998e1438 | Ori Rabin | include ParameterValidators
|
|
d7611b24 | Greg Sutcliffe | belongs_to :owner, :polymorphic => true
|
|
belongs_to :compute_resource
|
|||
belongs_to :image
|
|||
585f328e | Greg Sutcliffe | has_one :token, :foreign_key => :host_id, :dependent => :destroy
|
|
3e750719 | Daniel Lobato | before_destroy :remove_reports
|
|
d7611b24 | Greg Sutcliffe | ||
5dfb51bb | Tomer Brisker | def self.complete_for(query, opts = {})
|
|
c9363b77 | Tomer Brisker | matcher = /(\s*(?:(?:user\.[a-z]+)|owner)\s*[=~])\s*(\S*)\s*\z/
|
|
matches = matcher.match(query)
|
|||
output = super(query, opts)
|
|||
if matches.present? && 'current_user'.starts_with?(matches[2])
|
|||
current_user_result = query.sub(matcher, '\1 current_user')
|
|||
output = [current_user_result] + output
|
|||
end
|
|||
5dfb51bb | Tomer Brisker | output
|
|
end
|
|||
d7611b24 | Greg Sutcliffe | # Define custom hook that can be called in model by magic methods (before, after, around)
|
|
define_model_callbacks :build, :only => :after
|
|||
define_model_callbacks :provision, :only => :before
|
|||
# Custom hooks will be executed after_commit
|
|||
after_commit :build_hooks
|
|||
aa19255e | Dominic Cleal | before_save :clear_data_on_build
|
|
3dce1589 | Justin Sherrill | before_save :clear_puppetinfo, :if => :environment_id_changed?
|
|
83683ed0 | Tomer Brisker | after_save :update_hostgroups_puppetclasses, :if => :hostgroup_id_changed?
|
|
d7611b24 | Greg Sutcliffe | ||
04cb74c0 | Shimon Shtein | def initialize(attributes = nil, options = {})
|
|
attributes = apply_inherited_attributes(attributes, false)
|
|||
super(attributes, options)
|
|||
end
|
|||
d7611b24 | Greg Sutcliffe | def build_hooks
|
|
return unless respond_to?(:old) && old && (build? != old.build?)
|
|||
if build?
|
|||
run_callbacks :build do
|
|||
logger.debug { "custom hook after_build on #{name} will be executed if defined." }
|
|||
end
|
|||
else
|
|||
run_callbacks :provision do
|
|||
logger.debug { "custom hook before_provision on #{name} will be executed if defined." }
|
|||
end
|
|||
end
|
|||
end
|
|||
include HostCommon
|
|||
class Jail < ::Safemode::Jail
|
|||
13d9564d | Lukas Zapletal | allow :name, :diskLayout, :puppetmaster, :puppet_ca_server, :operatingsystem, :os, :environment, :ptable, :hostgroup,
|
|
bf75590c | Marek Hulan | :url_for_boot, :params, :info, :hostgroup, :compute_resource, :domain, :ip, :mac, :shortname, :architecture,
|
|
3d03e334 | Dominic Cleal | :model, :certname, :capabilities, :provider, :subnet, :token, :location, :organization, :provision_method,
|
|
43c4bd72 | Marek Hulan | :image_build?, :pxe_build?, :otp, :realm, :param_true?, :param_false?, :nil?, :indent, :primary_interface,
|
|
:provision_interface, :interfaces, :bond_interfaces, :interfaces_with_identifier, :managed_interfaces, :facts, :facts_hash, :root_pass,
|
|||
6ea461fe | Marek Hulan | :sp_name, :sp_ip, :sp_mac, :sp_subnet, :use_image,
|
|
:multiboot, :jumpstart_path, :install_path, :miniroot
|
|||
d7611b24 | Greg Sutcliffe | end
|
|
attr_reader :cached_host_params
|
|||
bb3572ff | Daniel Lobato | scope :recent, ->(*args) { {:conditions => ["last_report > ?", (args.first || (Setting[:puppet_interval] + Setting[:outofsync_interval]).minutes.ago)]} }
|
|
scope :out_of_sync, ->(*args) { {:conditions => ["last_report < ? and enabled != ?", (args.first || (Setting[:puppet_interval] + Setting[:outofsync_interval]).minutes.ago), false]} }
|
|||
d7611b24 | Greg Sutcliffe | ||
bb3572ff | Daniel Lobato | scope :with_os, -> { where('hosts.operatingsystem_id IS NOT NULL') }
|
|
d7611b24 | Greg Sutcliffe | ||
bb3572ff | Daniel Lobato | scope :with_error, lambda {
|
|
where("(puppet_status > 0) and
|
|||
d7611b24 | Greg Sutcliffe | ( ((puppet_status >> #{BIT_NUM*METRIC.index("failed")} & #{MAX}) != 0) or
|
|
f2c78d4a | Joseph Magen | ((puppet_status >> #{BIT_NUM*METRIC.index("failed_restarts")} & #{MAX}) != 0) )")
|
|
d7611b24 | Greg Sutcliffe | }
|
|
bb3572ff | Daniel Lobato | scope :without_error, lambda {
|
|
where("((puppet_status >> #{BIT_NUM*METRIC.index("failed")} & #{MAX}) = 0) and
|
|||
f2c78d4a | Joseph Magen | ((puppet_status >> #{BIT_NUM*METRIC.index("failed_restarts")} & #{MAX}) = 0)")
|
|
d7611b24 | Greg Sutcliffe | }
|
|
bb3572ff | Daniel Lobato | scope :with_changes, lambda {
|
|
where("(puppet_status > 0) and
|
|||
d7611b24 | Greg Sutcliffe | ( ((puppet_status >> #{BIT_NUM*METRIC.index("applied")} & #{MAX}) != 0) or
|
|
f2c78d4a | Joseph Magen | ((puppet_status >> #{BIT_NUM*METRIC.index("restarted")} & #{MAX}) != 0) )")
|
|
d7611b24 | Greg Sutcliffe | }
|
|
bb3572ff | Daniel Lobato | scope :without_changes, lambda {
|
|
where("((puppet_status >> #{BIT_NUM*METRIC.index("applied")} & #{MAX}) = 0) and
|
|||
f2c78d4a | Joseph Magen | ((puppet_status >> #{BIT_NUM*METRIC.index("restarted")} & #{MAX}) = 0)")
|
|
d7611b24 | Greg Sutcliffe | }
|
|
bb3572ff | Daniel Lobato | scope :with_pending_changes, -> { where("(puppet_status > 0) and ((puppet_status >> #{BIT_NUM*METRIC.index("pending")} & #{MAX}) != 0)") }
|
|
scope :without_pending_changes, -> { where("((puppet_status >> #{BIT_NUM*METRIC.index("pending")} & #{MAX}) = 0)") }
|
|||
d7611b24 | Greg Sutcliffe | ||
bb3572ff | Daniel Lobato | scope :successful, -> { without_changes.without_error.without_pending_changes}
|
|
d7611b24 | Greg Sutcliffe | ||
bb3572ff | Daniel Lobato | scope :alerts_disabled, -> { where(:enabled => false) }
|
|
d7611b24 | Greg Sutcliffe | ||
bb3572ff | Daniel Lobato | scope :alerts_enabled, -> { where(:enabled => true) }
|
|
d7611b24 | Greg Sutcliffe | ||
scope :run_distribution, lambda { |fromtime,totime|
|
|||
if fromtime.nil? or totime.nil?
|
|||
bfbf7ed8 | Lukas Zapletal | raise ::Foreman.Exception.new(N_("invalid time range"))
|
|
d7611b24 | Greg Sutcliffe | else
|
|
f2c78d4a | Joseph Magen | joins("INNER JOIN reports ON reports.host_id = hosts.id").where("reports.reported_at BETWEEN ? AND ?", fromtime, totime)
|
|
d7611b24 | Greg Sutcliffe | end
|
|
}
|
|||
bb3572ff | Daniel Lobato | scope :for_token, ->(token) { joins(:token).where(:tokens => { :value => token }).where("expires >= ?", Time.now.utc.to_s(:db)).select('hosts.*') }
|
|
d7611b24 | Greg Sutcliffe | ||
bb3572ff | Daniel Lobato | scope :for_vm, ->(cr,vm) { where(:compute_resource_id => cr.id, :uuid => Array.wrap(vm).compact.map(&:identity)) }
|
|
3ccd0ef6 | Jason Montleon | ||
d7611b24 | Greg Sutcliffe | # audit the changes to this model
|
|
9c864cb6 | Ohad Levy | audited :except => [:last_report, :puppet_status, :last_compile], :allow_mass_assignment => true
|
|
d7611b24 | Greg Sutcliffe | has_associated_audits
|
|
# some shortcuts
|
|||
alias_attribute :os, :operatingsystem
|
|||
alias_attribute :arch, :architecture
|
|||
3dce1589 | Justin Sherrill | validates :environment_id, :presence => true, :unless => Proc.new { |host| host.puppet_proxy_id.blank? }
|
|
160e24ea | Joseph Magen | validates :organization_id, :presence => true, :if => Proc.new {|host| host.managed? && SETTINGS[:organizations_enabled] }
|
|
validates :location_id, :presence => true, :if => Proc.new {|host| host.managed? && SETTINGS[:locations_enabled] }
|
|||
d7611b24 | Greg Sutcliffe | ||
if SETTINGS[:unattended]
|
|||
# handles all orchestration of smart proxies.
|
|||
include Foreman::Renderer
|
|||
include Orchestration
|
|||
43c4bd72 | Marek Hulan | # DHCP orchestration delegation
|
|
delegate :dhcp?, :dhcp_record, :to => :primary_interface
|
|||
# DNS orchestration delegation
|
|||
delegate :dns?, :reverse_dns?, :dns_a_record, :dns_ptr_record, :to => :primary_interface
|
|||
d7611b24 | Greg Sutcliffe | include Orchestration::Compute
|
|
43c4bd72 | Marek Hulan | include Rails.application.routes.url_helpers
|
|
# TFTP orchestration delegation
|
|||
delegate :tftp?, :tftp, :generate_pxe_template, :to => :provision_interface
|
|||
d7611b24 | Greg Sutcliffe | include Orchestration::Puppetca
|
|
include Orchestration::SSHProvision
|
|||
77f70152 | Stephen Benjamin | include Orchestration::Realm
|
|
d7611b24 | Greg Sutcliffe | include HostTemplateHelpers
|
|
4d5b9795 | Dominic Cleal | delegate :fqdn, :fqdn_changed?, :fqdn_was, :shortname, :to => :primary_interface,
|
|
43c4bd72 | Marek Hulan | :allow_nil => true
|
|
delegate :require_ip_validation?, :to => :provision_interface
|
|||
d7611b24 | Greg Sutcliffe | ||
43c4bd72 | Marek Hulan | validates :architecture_id, :operatingsystem_id, :presence => true, :if => Proc.new {|host| host.managed}
|
|
c4bfd47f | Stephen Benjamin | validates :root_pass, :length => {:minimum => 8, :message => _('should be 8 characters or more')},
|
|
:presence => {:message => N_('should not be blank - consider setting a global or host group default')},
|
|||
aea52e15 | Christine Fouant | :if => Proc.new { |host| host.managed && host.pxe_build? && build? }
|
|
4c60237a | Jiayi Ye | validates :ptable_id, :presence => {:message => N_("can't be blank unless a custom partition has been defined")},
|
|
aea52e15 | Christine Fouant | :if => Proc.new { |host| host.managed and host.disk.empty? and not Foreman.in_rake? and host.pxe_build? and host.build? }
|
|
3d03e334 | Dominic Cleal | validates :provision_method, :inclusion => {:in => PROVISION_METHODS, :message => N_('is unknown')}, :if => Proc.new {|host| host.managed?}
|
|
316d78c0 | Joseph Magen | validates :medium_id, :presence => true, :if => Proc.new { |host| host.validate_media? }
|
|
3d03e334 | Dominic Cleal | validate :provision_method_in_capabilities
|
|
43c4bd72 | Marek Hulan | validate :short_name_periods
|
|
b6ad9fc9 | Dmitri Dolguikh | before_validation :set_compute_attributes, :on => :create
|
|
57e4204b | Joseph Magen | validate :check_if_provision_method_changed, :on => :update, :if => Proc.new { |host| host.managed }
|
|
ae274f95 | Ondrej Prazak | else
|
|
def fqdn
|
|||
facts['fqdn'] || name
|
|||
end
|
|||
def compute?
|
|||
false
|
|||
end
|
|||
def compute_provides?(attr)
|
|||
false
|
|||
end
|
|||
d7611b24 | Greg Sutcliffe | end
|
|
43c4bd72 | Marek Hulan | before_validation :set_hostgroup_defaults, :set_ip_address
|
|
7fcb314e | Daniel Lobato | after_validation :ensure_associations, :set_default_user
|
|
d7611b24 | Greg Sutcliffe | before_validation :set_certname, :if => Proc.new {|h| h.managed? and Setting[:use_uuid_for_certificates] } if SETTINGS[:unattended]
|
|
43c4bd72 | Marek Hulan | after_validation :trigger_nic_orchestration, :if => Proc.new { |h| h.managed? && h.changed? }, :on => :update
|
|
60fdfb38 | Marek Hulan | before_validation :validate_dns_name_uniqueness
|
|
d7611b24 | Greg Sutcliffe | ||
def <=>(other)
|
|||
self.name <=> other.name
|
|||
end
|
|||
# method to return the correct owner list for host edit owner select dropbox
|
|||
def is_owned_by
|
|||
owner.id_and_type if owner
|
|||
end
|
|||
54134869 | Ohad Levy | def self.model_name
|
|
ActiveModel::Name.new(Host)
|
|||
end
|
|||
d7611b24 | Greg Sutcliffe | # virtual attributes which sets the owner based on the user selection
|
|
# supports a simple user, or a usergroup
|
|||
# selection parameter is expected to be an ActiveRecord id_and_type method (see Foreman's AR extentions).
|
|||
def is_owned_by=(selection)
|
|||
a6b0eeb0 | Joseph Magen | oid = User.find(selection.to_i) if selection =~ (/-Users\Z/)
|
|
oid = Usergroup.find(selection.to_i) if selection =~ (/-Usergroups\Z/)
|
|||
d7611b24 | Greg Sutcliffe | self.owner = oid
|
|
end
|
|||
def clearReports
|
|||
# Remove any reports that may be held against this host
|
|||
f2c78d4a | Joseph Magen | Report.where("host_id = #{id}").delete_all
|
|
d7611b24 | Greg Sutcliffe | end
|
|
def clearFacts
|
|||
f2c78d4a | Joseph Magen | FactValue.where("host_id = #{id}").delete_all
|
|
d7611b24 | Greg Sutcliffe | end
|
|
aa19255e | Dominic Cleal | def clear_data_on_build
|
|
return unless respond_to?(:old) && old && build? && !old.build?
|
|||
clearFacts
|
|||
clearReports
|
|||
end
|
|||
d7611b24 | Greg Sutcliffe | def set_token
|
|
return unless Setting[:token_duration] != 0
|
|||
c2ff4bd6 | Ori Rabin | self.build_token(:value => Foreman.uuid,
|
|
:expires => Time.now.utc + Setting[:token_duration].minutes)
|
|||
d7611b24 | Greg Sutcliffe | end
|
|
585f328e | Greg Sutcliffe | def expire_token
|
|
self.token.delete if self.token.present?
|
|||
d7611b24 | Greg Sutcliffe | end
|
|
# Called from the host build post install process to indicate that the base build has completed
|
|||
# Build is cleared and the boot link and autosign entries are removed
|
|||
# A site specific build script is called at this stage that can do site specific tasks
|
|||
def built(installed = true)
|
|||
# delete all expired tokens
|
|||
self.build = false
|
|||
77f70152 | Stephen Benjamin | self.otp = nil
|
|
d7611b24 | Greg Sutcliffe | self.installed_at = Time.now.utc if installed
|
|
1ef36c07 | Stephen Benjamin | ||
if self.save
|
|||
recipients = owner ? owner.recipients_for(:host_built) : []
|
|||
MailNotification[:host_built].deliver(self, :users => recipients) if recipients.present?
|
|||
true
|
|||
else
|
|||
logger.warn "Failed to set Build on #{self}: #{self.errors.full_messages}"
|
|||
false
|
|||
end
|
|||
d7611b24 | Greg Sutcliffe | end
|
|
#retuns fqdn of host puppetmaster
|
|||
def pm_fqdn
|
|||
puppetmaster == "puppet" ? "puppet.#{domain.name}" : "#{puppetmaster}"
|
|||
end
|
|||
# Cleans Certificate and enable Autosign
|
|||
77f70152 | Stephen Benjamin | # Called before a host is given their provisioning template
|
|
d7611b24 | Greg Sutcliffe | # Returns : Boolean status of the operation
|
|
def handle_ca
|
|||
89e506f7 | Aaron Stone | # If there's no puppetca, tell the caller that everything is ok
|
|
d7611b24 | Greg Sutcliffe | return true unless Setting[:manage_puppetca]
|
|
f09d61de | Dominic Cleal | return true unless puppetca?
|
|
89e506f7 | Aaron Stone | ||
# From here out, we expect things to work and return true
|
|||
return false unless respond_to?(:initialize_puppetca, true)
|
|||
return false unless initialize_puppetca
|
|||
return false unless delCertificate
|
|||
d2823e35 | Aaron Stone | # If use_uuid_for_certificates is true, reuse the certname UUID value.
|
|
# If false, then reset the certname if it does not match the hostname.
|
|||
if (Setting[:use_uuid_for_certificates] ? !Foreman.is_uuid?(certname) : certname != hostname)
|
|||
logger.info "Removing certificate value #{certname} for host #{name}"
|
|||
89e506f7 | Aaron Stone | self.certname = nil
|
|
end
|
|||
setAutosign
|
|||
d7611b24 | Greg Sutcliffe | end
|
|
77f70152 | Stephen Benjamin | # Request a new OTP for a host
|
|
def handle_realm
|
|||
return true unless realm?
|
|||
# If no OTP is set, then this is probably a rebuild
|
|||
if self.otp.blank?
|
|||
logger.info "Setting realm for host #{name}"
|
|||
set_realm :rebuild => true
|
|||
self.save!
|
|||
else
|
|||
true
|
|||
end
|
|||
end
|
|||
d7611b24 | Greg Sutcliffe | # returns the host correct disk layout, custom or common
|
|
def diskLayout
|
|||
@host = self
|
|||
de9e7ada | Marek Hulan | template = disk.blank? ? ptable.layout : disk
|
|
pxe_render(template.tr("\r", ''))
|
|||
d7611b24 | Greg Sutcliffe | end
|
|
510d53cd | Marek Hulan | def configTemplate(args = {})
|
|
319d1ffb | alongoldboim | Foreman::Deprecation.deprecation_warning("1.11", 'configTemplate was renamed to provisioning_template')
|
|
510d53cd | Marek Hulan | self.provisioning_template(args)
|
|
end
|
|||
d7611b24 | Greg Sutcliffe | # returns a configuration template (such as kickstart) to a given host
|
|
510d53cd | Marek Hulan | def provisioning_template(opts = {})
|
|
d7611b24 | Greg Sutcliffe | opts[:kind] ||= "provision"
|
|
opts[:operatingsystem_id] ||= operatingsystem_id
|
|||
opts[:hostgroup_id] ||= hostgroup_id
|
|||
opts[:environment_id] ||= environment_id
|
|||
510d53cd | Marek Hulan | ProvisioningTemplate.find_template opts
|
|
d7611b24 | Greg Sutcliffe | end
|
|
# reports methods
|
|||
def error_count
|
|||
%w[failed failed_restarts].sum {|f| status f}
|
|||
end
|
|||
def no_report
|
|||
e57ed7b8 | Daniel Lobato | last_report.nil? or last_report < Time.now - (Setting[:puppet_interval] + Setting[:outofsync_interval]).minutes and enabled?
|
|
d7611b24 | Greg Sutcliffe | end
|
|
def disabled?
|
|||
not enabled?
|
|||
end
|
|||
111cde57 | Joseph Magen | # the environment used by #clases nees to be self.environment and not self.parent.environment
|
|
def parent_classes
|
|||
return [] unless hostgroup
|
|||
hostgroup.classes(environment)
|
|||
end
|
|||
def parent_config_groups
|
|||
return [] unless hostgroup
|
|||
hostgroup.all_config_groups
|
|||
end
|
|||
d7611b24 | Greg Sutcliffe | # returns the list of puppetclasses a host is in.
|
|
def puppetclasses_names
|
|||
all_puppetclasses.collect {|c| c.name}
|
|||
end
|
|||
# provide information about each node, mainly used for puppet external nodes
|
|||
# TODO: remove hard coded default parameters into some selectable values in the database.
|
|||
3dce1589 | Justin Sherrill | # rubocop:disable Metrics/PerceivedComplexity
|
|
# rubocop:disable Metrics/CyclomaticComplexity
|
|||
d7611b24 | Greg Sutcliffe | def info
|
|
# Static parameters
|
|||
param = {}
|
|||
# maybe these should be moved to the common parameters, leaving them in for now
|
|||
param["puppetmaster"] = puppetmaster
|
|||
param["domainname"] = domain.fullname unless domain.nil? or domain.fullname.nil?
|
|||
77d9d699 | Stephen Benjamin | param["realm"] = realm.name unless realm.nil?
|
|
d7611b24 | Greg Sutcliffe | param["hostgroup"] = hostgroup.to_label unless hostgroup.nil?
|
|
if SETTINGS[:locations_enabled]
|
|||
param["location"] = location.name unless location.blank?
|
|||
end
|
|||
if SETTINGS[:organizations_enabled]
|
|||
param["organization"] = organization.name unless organization.blank?
|
|||
end
|
|||
if SETTINGS[:unattended]
|
|||
331ff165 | William Hefter | param["root_pw"] = root_pass unless (!operatingsystem.nil? && operatingsystem.password_hash == 'Base64')
|
|
d7611b24 | Greg Sutcliffe | param["puppet_ca"] = puppet_ca_server if puppetca?
|
|
end
|
|||
param["comment"] = comment unless comment.blank?
|
|||
param["foreman_env"] = environment.to_s unless environment.nil? or environment.name.nil?
|
|||
if SETTINGS[:login] and owner
|
|||
param["owner_name"] = owner.name
|
|||
param["owner_email"] = owner.is_a?(User) ? owner.mail : owner.users.map(&:mail)
|
|||
end
|
|||
if Setting[:ignore_puppet_facts_for_provisioning]
|
|||
param["ip"] = ip
|
|||
param["mac"] = mac
|
|||
end
|
|||
e24c3fbb | Marek Hulan | param['foreman_subnets'] = interfaces.map(&:subnet).compact.map(&:to_enc).uniq
|
|
43c4bd72 | Marek Hulan | param['foreman_interfaces'] = interfaces.map(&:to_enc)
|
|
d7611b24 | Greg Sutcliffe | param.update self.params
|
|
84ae9603 | Greg Sutcliffe | # Parse ERB values contained in the parameters
|
|
param = SafeRender.new(:variables => { :host => self }).parse(param)
|
|||
3dce1589 | Justin Sherrill | classes = if self.environment.nil?
|
|
[]
|
|||
elsif Setting[:Parametrized_Classes_in_ENC] && Setting[:Enable_Smart_Variables_in_ENC]
|
|||
d7611b24 | Greg Sutcliffe | lookup_keys_class_params
|
|
else
|
|||
self.puppetclasses_names
|
|||
end
|
|||
info_hash = {}
|
|||
info_hash['classes'] = classes
|
|||
info_hash['parameters'] = param
|
|||
3dce1589 | Justin Sherrill | info_hash['environment'] = param["foreman_env"] if Setting["enc_environment"] && param["foreman_env"]
|
|
d7611b24 | Greg Sutcliffe | ||
info_hash
|
|||
end
|
|||
def params
|
|||
host_params.update(lookup_keys_params)
|
|||
end
|
|||
3a96ba00 | Amos Benari | ||
d7611b24 | Greg Sutcliffe | def clear_host_parameters_cache!
|
|
@cached_host_params = nil
|
|||
end
|
|||
5f029ed6 | Daniel Lobato | def host_inherited_params(include_source = false)
|
|
d7611b24 | Greg Sutcliffe | hp = {}
|
|
# read common parameters
|
|||
7669211c | Marek Hulan | CommonParameter.all.each {|p| hp.update Hash[p.name => include_source ? {:value => p.value, :source => N_('common').to_sym, :safe_value => p.safe_value} : p.value] }
|
|
1fa008a4 | Joseph Magen | # read organization and location parameters
|
|
hp.update organization.parameters(include_source) if SETTINGS[:organizations_enabled] && organization
|
|||
hp.update location.parameters(include_source) if SETTINGS[:locations_enabled] && location
|
|||
d7611b24 | Greg Sutcliffe | # read domain parameters
|
|
04c6b019 | Tiffany | domain.domain_parameters.each {|p| hp.update Hash[p.name => include_source ? {:value => p.value, :source => N_('domain').to_sym, :safe_value => p.safe_value, :source_name => domain.name} : p.value] } unless domain.nil?
|
|
d7611b24 | Greg Sutcliffe | # read OS parameters
|
|
04c6b019 | Tiffany | operatingsystem.os_parameters.each {|p| hp.update Hash[p.name => include_source ? {:value => p.value, :source => N_('os').to_sym, :safe_value => p.safe_value, :source_name => operatingsystem.to_label} : p.value] } unless operatingsystem.nil?
|
|
d7611b24 | Greg Sutcliffe | # read group parameters only if a host belongs to a group
|
|
1fa008a4 | Joseph Magen | hp.update hostgroup.parameters(include_source) if hostgroup
|
|
d7611b24 | Greg Sutcliffe | hp
|
|
end
|
|||
def host_params
|
|||
return cached_host_params unless cached_host_params.blank?
|
|||
hp = host_inherited_params
|
|||
# and now read host parameters, override if required
|
|||
host_parameters.each {|p| hp.update Hash[p.name => p.value] }
|
|||
@cached_host_params = hp
|
|||
end
|
|||
01055e77 | Greg Sutcliffe | # JSON is auto-parsed by the API, so these should be in the right format
|
|
5f029ed6 | Daniel Lobato | def self.import_host_and_facts(hostname, facts, certname = nil, proxy_id = nil)
|
|
01055e77 | Greg Sutcliffe | raise(::Foreman::Exception.new("Invalid Facts, must be a Hash")) unless facts.is_a?(Hash)
|
|
raise(::Foreman::Exception.new("Invalid Hostname, must be a String")) unless hostname.is_a?(String)
|
|||
# downcase everything
|
|||
hostname.try(:downcase!)
|
|||
certname.try(:downcase!)
|
|||
25a647eb | Joey D | facts['domain'].try(:downcase!)
|
|
01055e77 | Greg Sutcliffe | ||
e88536b2 | Daniel Lobato | host = certname.present? ? Host.find_by_certname(certname) : nil
|
|
host ||= Host.find_by_name hostname
|
|||
host ||= Host.new(:name => hostname, :certname => certname) if Setting[:create_new_host_when_facts_are_uploaded]
|
|||
01055e77 | Greg Sutcliffe | ||
e88536b2 | Daniel Lobato | return Host.new, true if host.nil?
|
|
01055e77 | Greg Sutcliffe | # if we were given a certname but found the Host by hostname we should update the certname
|
|
e88536b2 | Daniel Lobato | host.certname = certname if certname.present?
|
|
5ab79857 | Ohad Levy | ||
# if proxy authentication is enabled and we have no puppet proxy set, use it.
|
|||
e88536b2 | Daniel Lobato | host.puppet_proxy_id ||= proxy_id
|
|
5ab79857 | Ohad Levy | ||
e88536b2 | Daniel Lobato | host.save(:validate => false) if host.new_record?
|
|
state = host.import_facts(facts)
|
|||
96144a47 | Daniel Lobato | [host, state]
|
|
d7611b24 | Greg Sutcliffe | end
|
|
796352ed | Greg Sutcliffe | def attributes_to_import_from_facts
|
|
43c4bd72 | Marek Hulan | super + [:domain, :architecture, :operatingsystem]
|
|
f7bedf48 | Marek Hulan | end
|
|
1d750dd7 | Marek Hulan | def populate_fields_from_facts(facts = self.facts_hash, type = 'puppet')
|
|
796352ed | Greg Sutcliffe | importer = super
|
|
d7611b24 | Greg Sutcliffe | if Setting[:update_environment_from_facts]
|
|
set_non_empty_values importer, [:environment]
|
|||
else
|
|||
self.environment ||= importer.environment unless importer.environment.blank?
|
|||
end
|
|||
f6fb925e | alongoldboim | operatingsystem.architectures << architecture if operatingsystem && architecture && !operatingsystem.architectures.include?(architecture)
|
|
d7611b24 | Greg Sutcliffe | self.save(:validate => false)
|
|
end
|
|||
# Called by build link in the list
|
|||
# Build is set
|
|||
# The boot link and autosign entry are created
|
|||
# Any existing puppet certificates are deleted
|
|||
# Any facts are discarded
|
|||
def setBuild
|
|||
self.build = true
|
|||
self.save
|
|||
errors.empty?
|
|||
end
|
|||
# this method accepts a puppets external node yaml output and generate a node in our setup
|
|||
# it is assumed that you already have the node (e.g. imported by one of the rack tasks)
|
|||
5f029ed6 | Daniel Lobato | def importNode(nodeinfo)
|
|
d7611b24 | Greg Sutcliffe | myklasses= []
|
|
# puppet classes
|
|||
nodeinfo["classes"].each do |klass|
|
|||
if (pc = Puppetclass.find_by_name(klass))
|
|||
myklasses << pc
|
|||
else
|
|||
bfbf7ed8 | Lukas Zapletal | error = _("Failed to import %{klass} for %{name}: doesn't exists in our database - ignoring") % { :klass => klass, :name => name }
|
|
d7611b24 | Greg Sutcliffe | logger.warn error
|
|
$stdout.puts error
|
|||
end
|
|||
self.puppetclasses = myklasses
|
|||
end
|
|||
# parameters are a bit more tricky, as some classifiers provide the facts as parameters as well
|
|||
# not sure what is puppet priority about it, but we ignore it if has a fact with the same name.
|
|||
# additionally, we don't import any non strings values, as puppet don't know what to do with those as well.
|
|||
myparams = self.info["parameters"]
|
|||
nodeinfo["parameters"].each_pair do |param,value|
|
|||
next if fact_names.exists? :name => param
|
|||
next unless value.is_a?(String)
|
|||
# we already have this parameter
|
|||
next if myparams.has_key?(param) and myparams[param] == value
|
|||
unless (hp = self.host_parameters.create(:name => param, :value => value))
|
|||
logger.warn "Failed to import #{param}/#{value} for #{name}: #{hp.errors.full_messages.join(", ")}"
|
|||
4f7a4d0b | David Davis | $stdout.puts $ERROR_INFO
|
|
d7611b24 | Greg Sutcliffe | end
|
|
end
|
|||
46b3d8f1 | Dominic Cleal | self.clear_host_parameters_cache!
|
|
d7611b24 | Greg Sutcliffe | self.save
|
|
end
|
|||
# counts each association of a given host
|
|||
# e.g. how many hosts belongs to each os
|
|||
# returns sorted hash
|
|||
5f029ed6 | Daniel Lobato | def self.count_distribution(association)
|
|
870e7fcc | Amos Benari | output = []
|
|
acfbc458 | Marek Hulan | data = group("#{Host.table_name}.#{association}_id").reorder('').count
|
|
associations = association.to_s.camelize.constantize.where(:id => data.keys).all
|
|||
data.each do |k,v|
|
|||
d7611b24 | Greg Sutcliffe | begin
|
|
acfbc458 | Marek Hulan | output << {:label => associations.detect {|a| a.id == k }.to_label, :data => v } unless v == 0
|
|
d7611b24 | Greg Sutcliffe | rescue
|
|
logger.info "skipped #{k} as it has has no label"
|
|||
end
|
|||
end
|
|||
output
|
|||
end
|
|||
# counts each association of a given host for HABTM relationships
|
|||
# TODO: Merge these two into one method
|
|||
# e.g. how many hosts belongs to each os
|
|||
# returns sorted hash
|
|||
5f029ed6 | Daniel Lobato | def self.count_habtm(association)
|
|
acfbc458 | Marek Hulan | counter = Host::Managed.joins(association.tableize.to_sym).group("#{association.tableize.to_sym}.id").reorder('').count
|
|
d7611b24 | Greg Sutcliffe | #Puppetclass.find(counter.keys.compact)...
|
|
870e7fcc | Amos Benari | association.camelize.constantize.find(counter.keys.compact).map {|i| {:label=>i.to_label, :data =>counter[i.id]}}
|
|
d7611b24 | Greg Sutcliffe | end
|
|
def classes_from_storeconfigs
|
|||
klasses = resources.select(:title).where(:restype => "Class").where("title <> ? AND title <> ?", "main", "Settings").order(:title)
|
|||
klasses.map!(&:title).delete(:main)
|
|||
klasses
|
|||
end
|
|||
def can_be_built?
|
|||
3d03e334 | Dominic Cleal | managed? and SETTINGS[:unattended] and pxe_build? and !build?
|
|
d7611b24 | Greg Sutcliffe | end
|
|
def jumpstart?
|
|||
operatingsystem.family == "Solaris" and architecture.name =~/Sparc/i rescue false
|
|||
end
|
|||
04cb74c0 | Shimon Shtein | def hostgroup_inherited_attributes
|
|
%w{puppet_proxy_id puppet_ca_proxy_id environment_id compute_profile_id realm_id}
|
|||
end
|
|||
def apply_inherited_attributes(attributes, initialized = true)
|
|||
return nil unless attributes
|
|||
#don't change the source to minimize side effects.
|
|||
attributes = hash_clone(attributes)
|
|||
new_hostgroup_id = attributes['hostgroup_id'] || attributes['hostgroup_name']
|
|||
#hostgroup didn't change, no inheritance needs update.
|
|||
return attributes if new_hostgroup_id.blank?
|
|||
new_hostgroup = self.hostgroup if initialized
|
|||
unless [new_hostgroup.try(:id), new_hostgroup.try(:friendly_id)].include? new_hostgroup_id
|
|||
new_hostgroup = Hostgroup.find(new_hostgroup_id)
|
|||
end
|
|||
return attributes unless new_hostgroup
|
|||
inherited_attributes = hostgroup_inherited_attributes - attributes.keys
|
|||
inherited_attributes.each do |attribute|
|
|||
value = new_hostgroup.send("inherited_#{attribute}")
|
|||
attributes[attribute] = value
|
|||
end
|
|||
attributes
|
|||
end
|
|||
def hash_clone(value)
|
|||
if value.is_a? Hash
|
|||
hash_type = value.class
|
|||
return hash_type[value.map{ |k, v| [k, hash_clone(v)] }]
|
|||
end
|
|||
value
|
|||
end
|
|||
d7611b24 | Greg Sutcliffe | def set_hostgroup_defaults
|
|
return unless hostgroup
|
|||
04cb74c0 | Shimon Shtein | assign_hostgroup_attributes(%w{domain_id compute_profile_id})
|
|
d7611b24 | Greg Sutcliffe | if SETTINGS[:unattended] and (new_record? or managed?)
|
|
04cb74c0 | Shimon Shtein | assign_hostgroup_attributes(%w{operatingsystem_id architecture_id})
|
|
3d03e334 | Dominic Cleal | assign_hostgroup_attributes(%w{medium_id ptable_id subnet_id}) if pxe_build?
|
|
d7611b24 | Greg Sutcliffe | end
|
|
end
|
|||
c6e02bd3 | Joseph Magen | def set_compute_attributes
|
|
return unless compute_attributes.empty?
|
|||
return unless compute_profile_id && compute_resource_id
|
|||
self.compute_attributes = compute_resource.compute_profile_attributes_for(compute_profile_id)
|
|||
end
|
|||
d7611b24 | Greg Sutcliffe | def set_ip_address
|
|
feacea35 | Amos Benari | self.ip ||= subnet.unused_ip if subnet and SETTINGS[:unattended] and (new_record? or managed?)
|
|
d7611b24 | Greg Sutcliffe | end
|
|
3ccd0ef6 | Jason Montleon | def associate!(cr, vm)
|
|
self.uuid = vm.identity
|
|||
self.compute_resource_id = cr.id
|
|||
self.save!(:validate => false) # don't want to trigger callbacks
|
|||
end
|
|||
def disassociate!
|
|||
self.uuid = nil
|
|||
self.compute_resource_id = nil
|
|||
self.save!(:validate => false) # don't want to trigger callbacks
|
|||
end
|
|||
d7611b24 | Greg Sutcliffe | def puppetrun!
|
|
unless puppet_proxy.present?
|
|||
bfbf7ed8 | Lukas Zapletal | errors.add(:base, _("no puppet proxy defined - cant continue"))
|
|
d7611b24 | Greg Sutcliffe | logger.warn "unable to execute puppet run, no puppet proxies defined"
|
|
return false
|
|||
end
|
|||
ProxyAPI::Puppet.new({:url => puppet_proxy.url}).run fqdn
|
|||
rescue => e
|
|||
bfbf7ed8 | Lukas Zapletal | errors.add(:base, _("failed to execute puppetrun: %s") % e)
|
|
01e78260 | Ivan Nečas | Foreman::Logging.exception("Unable to execute puppet run", e)
|
|
d7611b24 | Greg Sutcliffe | false
|
|
end
|
|||
# if certname does not exist, use hostname instead
|
|||
def certname
|
|||
read_attribute(:certname) || name
|
|||
end
|
|||
def progress_report_id
|
|||
@progress_report_id ||= Foreman.uuid
|
|||
end
|
|||
def progress_report_id=(value)
|
|||
@progress_report_id = value
|
|||
end
|
|||
def capabilities
|
|||
66afbc33 | Joseph Mitchell Magen | compute_resource ? compute_resource.capabilities : [:build]
|
|
d7611b24 | Greg Sutcliffe | end
|
|
def provider
|
|||
if compute_resource_id
|
|||
compute_resource.provider_friendly_name
|
|||
else
|
|||
"BareMetal"
|
|||
end
|
|||
end
|
|||
# no need to store anything in the db if the password is our default
|
|||
def root_pass
|
|||
db176297 | Dominic Cleal | return read_attribute(:root_pass) if read_attribute(:root_pass).present?
|
|
return hostgroup.try(:root_pass) if hostgroup.try(:root_pass).present?
|
|||
Setting[:root_pass]
|
|||
d7611b24 | Greg Sutcliffe | end
|
|
def clone
|
|||
e67fc0bd | Joseph Magen | # do not copy system specific attributes
|
|
b64117f6 | Dominic Cleal | host = self.deep_clone(:include => [:host_config_groups, :host_classes, :host_parameters],
|
|
:except => [:name, :mac, :ip, :uuid, :certname, :last_report])
|
|||
43c4bd72 | Marek Hulan | self.interfaces.each do |nic|
|
|
host.interfaces << nic.clone
|
|||
end
|
|||
f5ab56ae | Dmitri Dolguikh | if self.compute_resource
|
|
host.compute_attributes = host.compute_resource.vm_compute_attributes_for(self.uuid)
|
|||
end
|
|||
e67fc0bd | Joseph Magen | host.puppet_status = 0
|
|
host
|
|||
d7611b24 | Greg Sutcliffe | end
|
|
40df7dfb | Daniel Lobato | def bmc_nic
|
|
interfaces.bmc.first
|
|||
end
|
|||
d7611b24 | Greg Sutcliffe | def sp_ip
|
|
bmc_nic.try(:ip)
|
|||
end
|
|||
def sp_mac
|
|||
bmc_nic.try(:mac)
|
|||
end
|
|||
def sp_subnet_id
|
|||
bmc_nic.try(:subnet_id)
|
|||
end
|
|||
def sp_subnet
|
|||
bmc_nic.try(:subnet)
|
|||
end
|
|||
def sp_name
|
|||
bmc_nic.try(:name)
|
|||
end
|
|||
7e8bfe82 | Walter Huf | def vm_compute_attributes
|
|
compute_resource ? compute_resource.vm_compute_attributes_for(uuid) : nil
|
|||
end
|
|||
d7611b24 | Greg Sutcliffe | def host_status
|
|
if build
|
|||
6a7658b9 | Lukas Zapletal | N_("Pending Installation")
|
|
d7611b24 | Greg Sutcliffe | elsif respond_to?(:enabled) && !enabled
|
|
6a7658b9 | Lukas Zapletal | N_("Alerts disabled")
|
|
d7611b24 | Greg Sutcliffe | elsif respond_to?(:last_report) && last_report.nil?
|
|
6a7658b9 | Lukas Zapletal | N_("No reports")
|
|
d7611b24 | Greg Sutcliffe | elsif no_report
|
|
6a7658b9 | Lukas Zapletal | N_("Out of sync")
|
|
d7611b24 | Greg Sutcliffe | elsif error?
|
|
6a7658b9 | Lukas Zapletal | N_("Error")
|
|
d7611b24 | Greg Sutcliffe | elsif changes?
|
|
6a7658b9 | Lukas Zapletal | N_("Active")
|
|
d7611b24 | Greg Sutcliffe | elsif pending?
|
|
6a7658b9 | Lukas Zapletal | N_("Pending")
|
|
d7611b24 | Greg Sutcliffe | else
|
|
6a7658b9 | Lukas Zapletal | N_("No changes")
|
|
d7611b24 | Greg Sutcliffe | end
|
|
end
|
|||
def smart_proxies
|
|||
SmartProxy.where(:id => smart_proxy_ids)
|
|||
end
|
|||
def smart_proxy_ids
|
|||
ids = []
|
|||
[subnet, hostgroup.try(:subnet)].compact.each do |s|
|
|||
ids << s.dhcp_id
|
|||
ids << s.tftp_id
|
|||
ids << s.dns_id
|
|||
end
|
|||
[domain, hostgroup.try(:domain)].compact.each do |d|
|
|||
ids << d.dns_id
|
|||
end
|
|||
77f70152 | Stephen Benjamin | [realm, hostgroup.try(:realm)].compact.each do |r|
|
|
ids << r.realm_proxy_id
|
|||
end
|
|||
d7611b24 | Greg Sutcliffe | [puppet_proxy_id, puppet_ca_proxy_id, hostgroup.try(:puppet_proxy_id), hostgroup.try(:puppet_ca_proxy_id)].compact.each do |p|
|
|
ids << p
|
|||
end
|
|||
ids.uniq.compact
|
|||
end
|
|||
40df7dfb | Daniel Lobato | def bmc_proxy
|
|
@bmc_proxy ||= bmc_nic.proxy
|
|||
end
|
|||
def bmc_available?
|
|||
ipmi = bmc_nic
|
|||
return false if ipmi.nil?
|
|||
ipmi.password.present? && ipmi.username.present? && ipmi.provider == 'IPMI'
|
|||
end
|
|||
def power
|
|||
opts = {:host => self}
|
|||
if compute_resource_id && uuid
|
|||
c1452df6 | Marek Hulan | PowerManager::Virt.new(opts)
|
|
40df7dfb | Daniel Lobato | elsif bmc_available?
|
|
c1452df6 | Marek Hulan | PowerManager::BMC.new(opts)
|
|
40df7dfb | Daniel Lobato | else
|
|
raise ::Foreman::Exception.new(N_("Unknown power management support - can't continue"))
|
|||
end
|
|||
end
|
|||
def ipmi_boot(booting_device)
|
|||
bmc_proxy.boot({:function => 'bootdevice', :device => booting_device})
|
|||
end
|
|||
c6e02bd3 | Joseph Magen | # take from hostgroup if compute_profile_id is nil
|
|
def compute_profile_id
|
|||
read_attribute(:compute_profile_id) || hostgroup.try(:compute_profile_id)
|
|||
end
|
|||
3d03e334 | Dominic Cleal | def provision_method
|
|
read_attribute(:provision_method) || capabilities.first.to_s
|
|||
end
|
|||
def image_build?
|
|||
self.provision_method == 'image'
|
|||
end
|
|||
def pxe_build?
|
|||
self.provision_method == 'build'
|
|||
end
|
|||
316d78c0 | Joseph Magen | def validate_media?
|
|
08d248fc | Joseph Magen | managed && pxe_build? && build?
|
|
316d78c0 | Joseph Magen | end
|
|
6e916e52 | Shlomi Zadok | def available_template_kinds(provisioning = nil)
|
|
kinds = if provisioning == 'image'
|
|||
cr = ComputeResource.find_by_id(self.compute_resource_id)
|
|||
images = cr.try(:images)
|
|||
if images.blank?
|
|||
[TemplateKind.find('finish')]
|
|||
else
|
|||
bde3e87f | Greg Sutcliffe | uuid = self.compute_attributes[cr.image_param_name]
|
|
6e916e52 | Shlomi Zadok | image_kind = images.find_by_uuid(uuid).try(:user_data) ? 'user_data' : 'finish'
|
|
[TemplateKind.find(image_kind)]
|
|||
end
|
|||
else
|
|||
TemplateKind.all
|
|||
end
|
|||
kinds.map do |kind|
|
|||
510d53cd | Marek Hulan | ProvisioningTemplate.find_template({ :kind => kind.name,
|
|
:operatingsystem_id => operatingsystem_id,
|
|||
:hostgroup_id => hostgroup_id,
|
|||
:environment_id => environment_id
|
|||
})
|
|||
6e916e52 | Shlomi Zadok | end.compact
|
|
end
|
|||
def render_template(template)
|
|||
@host = self
|
|||
unattended_render(template)
|
|||
end
|
|||
def build_status
|
|||
build_status = HostBuildStatus.new(self)
|
|||
build_status.check_all_statuses
|
|||
build_status
|
|||
end
|
|||
43c4bd72 | Marek Hulan | # we must also clone interfaces objects so we can detect their attribute changes
|
|
# method is public because it's used when we run orchestration from interface side
|
|||
def setup_clone
|
|||
return if new_record?
|
|||
@old = super { |clone| clone.interfaces = self.interfaces.map {|i| setup_object_clone(i) } }
|
|||
end
|
|||
d7611b24 | Greg Sutcliffe | private
|
|
60fdfb38 | Marek Hulan | # validate uniqueness can't prevent saving two interfaces that has same DNS name
|
|
# because the validation happens before transaction is committed, so data are not in DB
|
|||
# yet, this is the reason why we "reimplement" uniqueness validation
|
|||
def validate_dns_name_uniqueness
|
|||
dups = self.interfaces.group_by { |i| [ i.name, i.domain_id ] }.detect { |dns, nics| dns.first.present? && nics.count > 1 }
|
|||
if dups.present?
|
|||
dups.last.first.errors.add(:name, :taken)
|
|||
self.errors.add :interfaces, _('Some interfaces are invalid')
|
|||
return false
|
|||
end
|
|||
end
|
|||
7acc469b | Amos Benari | def lookup_value_match
|
|
674755f4 | Ori Rabin | "fqdn=#{fqdn || name}"
|
|
7acc469b | Amos Benari | end
|
|
d7611b24 | Greg Sutcliffe | def lookup_keys_params
|
|
return {} unless Setting["Enable_Smart_Variables_in_ENC"]
|
|||
3a96ba00 | Amos Benari | Classification::GlobalParam.new(:host => self).enc
|
|
d7611b24 | Greg Sutcliffe | end
|
|
def lookup_keys_class_params
|
|||
3a96ba00 | Amos Benari | Classification::ClassParam.new(:host => self).enc
|
|
d7611b24 | Greg Sutcliffe | end
|
|
5f029ed6 | Daniel Lobato | def assign_hostgroup_attributes(attrs = [])
|
|
d7611b24 | Greg Sutcliffe | attrs.each do |attr|
|
|
5e1f3b71 | Tom Caspy | next if send(attr).to_i == -1
|
|
34897490 | Joseph Magen | value = hostgroup.send("inherited_#{attr}")
|
|
self.send("#{attr}=", value) unless send(attr).present?
|
|||
d7611b24 | Greg Sutcliffe | end
|
|
end
|
|||
# checks if the host association is a valid association for this host
|
|||
def ensure_associations
|
|||
status = true
|
|||
%w{ ptable medium architecture}.each do |e|
|
|||
value = self.send(e.to_sym)
|
|||
next if value.blank?
|
|||
unless os.send(e.pluralize.to_sym).include?(value)
|
|||
bfbf7ed8 | Lukas Zapletal | errors.add("#{e}_id".to_sym, _("%{value} does not belong to %{os} operating system") % { :value => value, :os => os })
|
|
d7611b24 | Greg Sutcliffe | status = false
|
|
end
|
|||
3d03e334 | Dominic Cleal | end if SETTINGS[:unattended] and managed? and os and pxe_build?
|
|
d7611b24 | Greg Sutcliffe | ||
feacea35 | Amos Benari | puppetclasses.select("puppetclasses.id,puppetclasses.name").uniq.each do |e|
|
|
unless environment.puppetclasses.map(&:id).include?(e.id)
|
|||
e52abb10 | Marek Hulan | errors.add(:puppetclasses, _("%{e} does not belong to the %{environment} environment") % { :e => e, :environment => environment })
|
|
d7611b24 | Greg Sutcliffe | status = false
|
|
end
|
|||
end if environment
|
|||
status
|
|||
end
|
|||
# alias to ensure same method that resolves the last report between the hosts and reports tables.
|
|||
def reported_at
|
|||
last_report
|
|||
end
|
|||
# puppet report status table column name
|
|||
def self.report_status
|
|||
"puppet_status"
|
|||
end
|
|||
# converts a name into ip address using DNS.
|
|||
# if we are managing DNS, we can query the correct DNS server
|
|||
# otherwise, use normal systems dns settings to resolv
|
|||
5f029ed6 | Daniel Lobato | def to_ip_address(name_or_ip)
|
|
d7611b24 | Greg Sutcliffe | return name_or_ip if name_or_ip =~ Net::Validations::IP_REGEXP
|
|
c83e29ac | Lukas Zapletal | if dns_ptr_record
|
|
lookup = dns_ptr_record.dns_lookup(name_or_ip)
|
|||
return lookup.ip unless lookup.nil?
|
|||
end
|
|||
d7611b24 | Greg Sutcliffe | # fall back to normal dns resolution
|
|
domain.resolver.getaddress(name_or_ip).to_s
|
|||
c83e29ac | Lukas Zapletal | rescue => e
|
|
logger.warn "Unable to find IP address for '#{name_or_ip}': #{e}"
|
|||
raise ::Foreman::WrappedException.new(e, N_("Unable to find IP address for '%s'"), name_or_ip)
|
|||
d7611b24 | Greg Sutcliffe | end
|
|
def set_default_user
|
|||
19579f87 | Martin Ducar | return if self.owner_type.present? && !OWNER_TYPES.include?(self.owner_type)
|
|
self.owner_type ||= 'User'
|
|||
d7611b24 | Greg Sutcliffe | self.owner ||= User.current
|
|
end
|
|||
def set_certname
|
|||
self.certname = Foreman.uuid if read_attribute(:certname).blank? or new_record?
|
|||
end
|
|||
3d03e334 | Dominic Cleal | def provision_method_in_capabilities
|
|
return unless managed?
|
|||
errors.add(:provision_method, _('is an unsupported provisioning method')) unless capabilities.map(&:to_s).include?(self.provision_method)
|
|||
end
|
|||
d7611b24 | Greg Sutcliffe | ||
57e4204b | Joseph Magen | def check_if_provision_method_changed
|
|
if self.provision_method_changed?
|
|||
errors.add(:provision_method, _("can't be updated after host is provisioned"))
|
|||
end
|
|||
end
|
|||
43c4bd72 | Marek Hulan | def short_name_periods
|
|
errors.add(:name, _("must not include periods")) if ( managed? && shortname && shortname.include?(".") && SETTINGS[:unattended] )
|
|||
89730c3c | Trey Dockendorf | end
|
|
83683ed0 | Tomer Brisker | def update_hostgroups_puppetclasses
|
|
Hostgroup.find(hostgroup_id_was).update_puppetclasses_total_hosts if hostgroup_id_was.present?
|
|||
Hostgroup.find(hostgroup_id).update_puppetclasses_total_hosts if hostgroup_id.present?
|
|||
end
|
|||
43c4bd72 | Marek Hulan | # we need this so when attribute like build changes we trigger tftp orchestration so token is updated on tftp
|
|
# but we should trigger it only for existing records and unless interfaces also changed (then validation is run
|
|||
# on them automatically)
|
|||
def trigger_nic_orchestration
|
|||
self.primary_interface.valid? unless self.primary_interface.changed?
|
|||
if self.primary_interface != self.provision_interface && !self.provision_interface.changed?
|
|||
self.provision_interface.valid?
|
|||
end
|
|||
end
|
|||
3e750719 | Daniel Lobato | ||
# For performance reasons logs and reports are deleted in batch
|
|||
# see http://projects.theforeman.org/issues/8316 for details
|
|||
def remove_reports
|
|||
return if reports.empty?
|
|||
Log.delete_all("report_id IN (#{reports.pluck(:id).join(',')})")
|
|||
Report.delete_all("host_id = #{id}")
|
|||
end
|
|||
3dce1589 | Justin Sherrill | ||
def clear_puppetinfo
|
|||
unless environment
|
|||
self.puppetclasses = []
|
|||
self.config_groups = []
|
|||
end
|
|||
end
|
|||
d7611b24 | Greg Sutcliffe | end
|