foreman/app/models/operatingsystem.rb @ b7fc06c4
2c83f744 | Paul Kelly | require 'ostruct'
|
|
require 'uri'
|
|||
4deab2f3 | Lukas Zapletal | class Operatingsystem < ApplicationRecord
|
|
a03e5341 | Marek Hulan | audited
|
|
acfbc458 | Marek Hulan | include Authorizable
|
|
5031bb10 | Tomas Strachota | include ValidateOsFamily
|
|
4cbf879e | Lukas Zapletal | include PxeLoaderSupport
|
|
8b737c9c | Joseph Magen | extend FriendlyId
|
|
friendly_id :title
|
|||
d7611b24 | Greg Sutcliffe | ||
3034e8e2 | Ori Rabin | validates_lengths_from_database
|
|
ff8cc704 | Joseph Mitchell Magen | before_destroy EnsureNotUsedBy.new(:hosts, :hostgroups)
|
|
d7611b24 | Greg Sutcliffe | has_many_hosts
|
|
7d993b41 | Joseph Mitchell Magen | has_many :hostgroups
|
|
dd42df0a | Ohad Levy | has_many :images, :dependent => :destroy
|
|
db59a916 | Jochen Schalanda | has_and_belongs_to_many :media
|
|
741bd717 | Daniel Lobato | has_and_belongs_to_many :ptables, :join_table => :operatingsystems_ptables, :foreign_key => :operatingsystem_id, :association_foreign_key => :ptable_id
|
|
ffc12fd6 | Ohad Levy | has_and_belongs_to_many :architectures
|
|
c6eee281 | Ohad Levy | has_and_belongs_to_many :puppetclasses
|
|
741bd717 | Daniel Lobato | has_and_belongs_to_many :provisioning_templates, :join_table => :operatingsystems_provisioning_templates, :foreign_key => :operatingsystem_id, :association_foreign_key => :provisioning_template_id
|
|
cab0d8c6 | Ohad Levy | has_many :os_default_templates, :dependent => :destroy
|
|
accepts_nested_attributes_for :os_default_templates, :allow_destroy => true,
|
|||
510d53cd | Marek Hulan | :reject_if => :reject_empty_provisioning_template
|
|
cab0d8c6 | Ohad Levy | ||
3034e8e2 | Ori Rabin | validates :major, :numericality => {:greater_than_or_equal_to => 0}, :presence => { :message => N_("Operating System version is required") }
|
|
998e1438 | Ori Rabin | has_many :os_parameters, :dependent => :destroy, :foreign_key => :reference_id, :inverse_of => :operatingsystem
|
|
57526a20 | Joseph Mitchell Magen | has_many :parameters, :dependent => :destroy, :foreign_key => :reference_id, :class_name => "OsParameter"
|
|
32ced385 | Ori Rabin | accepts_nested_attributes_for :os_parameters, :allow_destroy => true
|
|
998e1438 | Ori Rabin | include ParameterValidators
|
|
fe4629de | rbirnie | has_many :trends, :as => :trendable, :class_name => "ForemanTrend"
|
|
fb9f45e8 | Daniel Lobato | ||
42c9541f | Joseph Magen | attr_name :to_label
|
|
3034e8e2 | Ori Rabin | validates :minor, :numericality => {:greater_than_or_equal_to => 0}, :allow_nil => true, :allow_blank => true
|
|
59b23095 | Shlomi Zadok | validates :name, :presence => true, :no_whitespace => true,
|
|
:uniqueness => { :scope => [:major, :minor], :message => N_("Operating system version already exists")}
|
|||
42c9541f | Joseph Magen | validates :description, :uniqueness => true, :allow_blank => true
|
|
2d7f0315 | Dmitri Dolguikh | validates :password_hash, :inclusion => { :in => PasswordCrypt::ALGORITHMS }
|
|
59b23095 | Shlomi Zadok | before_validation :downcase_release_name, :set_title, :stringify_major_and_minor
|
|
8b737c9c | Joseph Magen | validates :title, :uniqueness => true, :presence => true
|
|
286a2207 | Ohad Levy | ||
c2c32409 | Greg Sutcliffe | before_save :set_family
|
|
5031bb10 | Tomas Strachota | ||
bb3572ff | Daniel Lobato | default_scope -> { order(:title) }
|
|
286a2207 | Ohad Levy | ||
c2c32409 | Greg Sutcliffe | scoped_search :on => :name, :complete_value => :true
|
|
scoped_search :on => :major, :complete_value => :true
|
|||
scoped_search :on => :minor, :complete_value => :true
|
|||
scoped_search :on => :description, :complete_value => :true
|
|||
scoped_search :on => :type, :complete_value => :true, :rename => "family"
|
|||
b948163b | Tomas Strachota | scoped_search :on => :title, :complete_value => :true
|
|
8de14697 | Ohad Levy | ||
ed67b8c9 | Dominic Cleal | scoped_search :relation => :architectures, :on => :name, :complete_value => :true, :rename => "architecture", :only_explicit => true
|
|
scoped_search :relation => :media, :on => :name, :complete_value => :true, :rename => "medium", :only_explicit => true
|
|||
scoped_search :relation => :provisioning_templates, :on => :name, :complete_value => :true, :rename => "template", :only_explicit => true
|
|||
9d43fc71 | Michael Moll | scoped_search :relation => :os_parameters, :on => :value, :on_key => :name, :complete_value => true, :rename => :params, :only_explicit => true
|
|
8de14697 | Ohad Levy | ||
48a65101 | Greg Sutcliffe | FAMILIES = { 'Debian' => %r{Debian|Ubuntu}i,
|
|
b1326294 | Michael Moll | 'Redhat' => %r{RedHat|Centos|Fedora|Scientific|SLC|OracleLinux}i,
|
|
48a65101 | Greg Sutcliffe | 'Suse' => %r{OpenSuSE|SLES|SLED}i,
|
|
'Windows' => %r{Windows}i,
|
|||
22671c50 | Kot | 'Altlinux' => %r{Altlinux}i,
|
|
ba71c565 | Greg Sutcliffe | 'Archlinux' => %r{Archlinux}i,
|
|
5a594178 | Johannes Scheuermann | 'Coreos' => %r{CoreOS}i,
|
|
0ace99ee | Enzo Hamelin | 'Rancheros' => %r{RancherOS}i,
|
|
48a65101 | Greg Sutcliffe | 'Gentoo' => %r{Gentoo}i,
|
|
'Solaris' => %r{Solaris}i,
|
|||
7e2880b6 | Ruediger Mueck | 'Freebsd' => %r{FreeBSD}i,
|
|
b80c6c00 | Frank Wall | 'AIX' => %r{AIX}i,
|
|
7d62413f | Fernando Carolo | 'Junos' => %r{Junos}i,
|
|
7cac0899 | Kyle Flavin | 'NXOS' => %r{NX-OS}i,
|
|
'Xenserver' => %r{XenServer}i }
|
|||
32847027 | Justin Sherrill | ||
class Jail < Safemode::Jail
|
|||
8ae9d962 | Tomer Brisker | allow :name, :media_url, :major, :minor, :family, :to_s, :repos, :==, :release, :release_name, :kernel, :initrd, :pxe_type, :medium_uri, :boot_files_uri, :password_hash
|
|
32847027 | Justin Sherrill | end
|
|
833e2aef | Amir Fefer | def self.title_name
|
|
"title".freeze
|
|||
end
|
|||
1285cc0d | Dominic Cleal | def self.inherited(child)
|
|
child.instance_eval do
|
|||
# Ensure all subclasses behave in the same way as the parent, and remain
|
|||
# identified as Operatingsystems instead of subclasses in UI paths etc.
|
|||
#
|
|||
# rubocop:disable Rails/Delegate
|
|||
def model_name
|
|||
superclass.model_name
|
|||
end
|
|||
# rubocop:enable Rails/Delegate
|
|||
end
|
|||
super
|
|||
end
|
|||
2c83f744 | Paul Kelly | # As Rails loads an object it casts it to the class in the 'type' field. If we ensure that the type and
|
|
# family are the same thing then rails converts the record to a Debian or a solaris object as required.
|
|||
# Manually managing the 'type' field allows us to control the inheritance chain and the available methods
|
|||
5f75dccc | Paul Kelly | def family
|
|
74275f51 | Michael Moll | self[:type]
|
|
5f75dccc | Paul Kelly | end
|
|
2c83f744 | Paul Kelly | def family=(value)
|
|
self.type = value
|
|||
end
|
|||
def self.families
|
|||
FAMILIES.keys.sort
|
|||
end
|
|||
5031bb10 | Tomas Strachota | validate_inclusion_in_families :type
|
|
2c83f744 | Paul Kelly | ||
def self.families_as_collection
|
|||
48a65101 | Greg Sutcliffe | families.map do |f|
|
|
OpenStruct.new(:name => f.constantize.new.display_family, :value => f)
|
|||
end
|
|||
2c83f744 | Paul Kelly | end
|
|
6b27556a | Amos Benari | # Operating system family can override this method to provide an array of
|
|
# hashes, each describing a repository. For example, to describe a yum repo,
|
|||
# the following structure can be returned by the method:
|
|||
# [{ :baseurl => "https://dl.thesource.com/get/it/here",
|
|||
# :name => "awesome",
|
|||
# :description => "awesome product repo"",
|
|||
# :enabled => 1,
|
|||
# :gpgcheck => 1
|
|||
# }]
|
|||
5f029ed6 | Daniel Lobato | def repos(host)
|
|
6b27556a | Amos Benari | []
|
|
end
|
|||
5f029ed6 | Daniel Lobato | def medium_uri(host, url = nil)
|
|
db59a916 | Jochen Schalanda | url ||= host.medium.path
|
|
f23483a2 | johscheuer | medium_vars_to_uri(url, host.architecture.name, host.operatingsystem)
|
|
0f77c7f2 | Ohad Levy | end
|
|
4f7a4d0b | David Davis | def medium_vars_to_uri(url, arch, os)
|
|
a6db0470 | Paul Kelly | URI.parse(interpolate_medium_vars(url, arch, os)).normalize
|
|
5f75dccc | Paul Kelly | end
|
|
5f029ed6 | Daniel Lobato | def interpolate_medium_vars(path, arch, os)
|
|
a6db0470 | Paul Kelly | return "" if path.empty?
|
|
f4459c11 | David Davis | path.gsub('$arch', arch).
|
|
a6db0470 | Paul Kelly | gsub('$major', os.major).
|
|
gsub('$minor', os.minor).
|
|||
7560679b | Daniel Lobato | gsub('$version', os.minor.blank? ? os.major : [os.major, os.minor].compact.join('.')).
|
|
20b2ec5b | Michael Moll | gsub('$release', os.release_name.presence || '')
|
|
a6db0470 | Paul Kelly | end
|
|
68f7a705 | Ohad Levy | # The OS is usually represented as the concatenation of the OS and the revision
|
|
286a2207 | Ohad Levy | def to_label
|
|
42c9541f | Joseph Magen | return description if description.present?
|
|
fullname
|
|||
end
|
|||
# to_label setter updates description and does not try to parse and update major, minor attributes
|
|||
def to_label=(str)
|
|||
self.description = str
|
|||
fd8666ab | Ohad Levy | end
|
|
47ab039e | Shlomi Zadok | def to_param
|
|
Parameterizable.parameterize("#{id}-#{title}")
|
|||
end
|
|||
fd8666ab | Ohad Levy | def release
|
|
85021506 | Michael Moll | "#{major}#{('.' + minor.to_s) if minor.present?}"
|
|
286a2207 | Ohad Levy | end
|
|
42c9541f | Joseph Magen | def fullname
|
|
c2c32409 | Greg Sutcliffe | "#{name} #{release}"
|
|
290c4d84 | Ohad Levy | end
|
|
42c9541f | Joseph Magen | def to_s
|
|
fullname
|
|||
3312a03d | Ohad Levy | end
|
|
5f75dccc | Paul Kelly | ||
42c9541f | Joseph Magen | def self.find_by_to_label(str)
|
|
27752930 | kgaikwad | os = self.find_by_description(str.to_s)
|
|
42c9541f | Joseph Magen | return os if os
|
|
a = str.split(" ")
|
|||
b1f4f883 | Joseph Mitchell Magen | b = a[1].split('.') if a[1]
|
|
cond = {:name => a[0]}
|
|||
cabe2c2e | Ohad Levy | cond[:major] = b[0] if b && b[0]
|
|
cond[:minor] = b[1] if b && b[1]
|
|||
8ac0ffd9 | Michael Moll | self.find_by(cond)
|
|
b1f4f883 | Joseph Mitchell Magen | end
|
|
4cbf879e | Lukas Zapletal | # Implemented only in the OSs subclasses where it makes sense
|
|
def available_loaders
|
|||
["None", "PXELinux BIOS"]
|
|||
end
|
|||
0f77c7f2 | Ohad Levy | # sets the prefix for the tfp files based on the os / arch combination
|
|
def pxe_prefix(arch)
|
|||
3cd8c84b | Michael Moll | "boot/#{self}-#{arch}".tr(" ", "-")
|
|
0f77c7f2 | Ohad Levy | end
|
|
316d78c0 | Joseph Magen | def pxe_files(medium, arch, host = nil)
|
|
boot_files_uri(medium, arch, host).collect do |img|
|
|||
0f77c7f2 | Ohad Levy | { pxe_prefix(arch).to_sym => img.to_s}
|
|
end
|
|||
end
|
|||
5f029ed6 | Daniel Lobato | def kernel(arch)
|
|
3cd8c84b | Michael Moll | bootfile(arch, :kernel)
|
|
218bd6e0 | Justin Sherrill | end
|
|
5f029ed6 | Daniel Lobato | def initrd(arch)
|
|
3cd8c84b | Michael Moll | bootfile(arch, :initrd)
|
|
218bd6e0 | Justin Sherrill | end
|
|
5f029ed6 | Daniel Lobato | def bootfile(arch, type)
|
|
dcfd9647 | Tomer Brisker | pxe_prefix(arch) + "-" + self.family.constantize::PXEFILES[type.to_sym]
|
|
a6db0470 | Paul Kelly | end
|
|
# Does this OS family support a build variant that is constructed from a prebuilt archive
|
|||
def supports_image
|
|||
false
|
|||
end
|
|||
4cbf879e | Lukas Zapletal | # Compatible kinds for this OS sorted by preferrence
|
|
def template_kinds
|
|||
b7fc06c4 | Lukas Zapletal | ["PXELinux", "PXEGrub2", "PXEGrub"]
|
|
a6db0470 | Paul Kelly | end
|
|
5f029ed6 | Daniel Lobato | def boot_filename(host = nil)
|
|
4cbf879e | Lukas Zapletal | return default_boot_filename if host.nil? || host.pxe_loader.nil?
|
|
4f5adf65 | Lukas Zapletal | self.class.all_loaders_map(host.arch.nil? ? '' : host.arch.bootfilename_efi)[host.pxe_loader]
|
|
a6db0470 | Paul Kelly | end
|
|
# Does this OS family use release_name in its naming scheme
|
|||
def use_release_name?
|
|||
false
|
|||
end
|
|||
def image_extension
|
|||
eed31c34 | Ohad Levy | raise ::Foreman::Exception.new(N_("Attempting to construct an operating system image filename but %s cannot be built from an image"), family)
|
|
a6db0470 | Paul Kelly | end
|
|
06bf16e9 | Ohad Levy | # If this OS family requires access to its media via NFS
|
|
8f7f710c | Amir Fefer | def self.require_nfs_access_to_medium
|
|
06bf16e9 | Ohad Levy | false
|
|
end
|
|||
48a65101 | Greg Sutcliffe | # Pretty method for displaying the Family name
|
|
def display_family
|
|||
"Unknown"
|
|||
end
|
|||
5f029ed6 | Daniel Lobato | def self.shorten_description(description)
|
|
c2c32409 | Greg Sutcliffe | # This method should be overridden in the OS subclass
|
|
# to handle shortening the specific formats of lsbdistdescription
|
|||
# returned by Facter on that OS
|
|||
description
|
|||
end
|
|||
2c83f744 | Paul Kelly | def deduce_family
|
|
c2c32409 | Greg Sutcliffe | self.family || self.class.families.find do |f|
|
|
5031bb10 | Tomas Strachota | name =~ FAMILIES[f]
|
|
2c83f744 | Paul Kelly | end
|
|
end
|
|||
c23e57af | Vincent Lequertier | def boot_files_uri(medium, architecture, host = nil)
|
|
a81a259c | Lukas Zapletal | raise ::Foreman::Exception.new(N_("%{os} medium was not set for host '%{host}'"), :host => host, :os => self) if medium.nil?
|
|
raise ::Foreman::Exception.new(N_("Invalid medium '%{medium}' for '%{os}'"), :medium => medium, :os => self) unless media.include?(medium)
|
|||
raise ::Foreman::Exception.new(N_("Invalid architecture '%{arch}' for '%{os}'"), :arch => architecture, :os => self) unless architectures.include?(architecture)
|
|||
dcfd9647 | Tomer Brisker | self.family.constantize::PXEFILES.values.map do |img|
|
|
c23e57af | Vincent Lequertier | medium_vars_to_uri("#{medium.path}/#{pxedir}/#{img}", architecture.name, self)
|
|
end
|
|||
end
|
|||
c2c32409 | Greg Sutcliffe | private
|
|
abd8f1d1 | Daniel Lobato | ||
c2c32409 | Greg Sutcliffe | def set_family
|
|
self.family ||= self.deduce_family
|
|||
end
|
|||
8b737c9c | Joseph Magen | def set_title
|
|
self.title = to_label.to_s[0..254]
|
|||
end
|
|||
59b23095 | Shlomi Zadok | def stringify_major_and_minor
|
|
# Cast major and minor to strings. see db/schema.rb around lines 560-562 (Or https://github.com/theforeman/foreman/blob/develop/db/migrate/20090720134126_create_operatingsystems.rb#L4).
|
|||
# Need to ensure type when using major and minor as scopes for name uniqueness.
|
|||
self.major = major.to_s
|
|||
self.minor = minor.to_s
|
|||
end
|
|||
9a9b3e75 | Paul Kelly | def downcase_release_name
|
|
976bf6e0 | Dominic Cleal | self.release_name = release_name.downcase if release_name.present?
|
|
9a9b3e75 | Paul Kelly | end
|
|
510d53cd | Marek Hulan | def reject_empty_provisioning_template(attributes)
|
|
c330aee0 | Shlomi Zadok | template_exists = attributes[:id].present?
|
|
510d53cd | Marek Hulan | provisioning_template_id_empty = attributes[:provisioning_template_id].blank?
|
|
cabe2c2e | Ohad Levy | attributes[:_destroy] = 1 if template_exists && provisioning_template_id_empty
|
|
510d53cd | Marek Hulan | (!template_exists && provisioning_template_id_empty)
|
|
c330aee0 | Shlomi Zadok | end
|
|
945de6b3 | Lukáš Zapletal | ||
# overriden by operating systems
|
|||
def pxe_kernel_options(params)
|
|||
[]
|
|||
end
|
|||
286a2207 | Ohad Levy | end
|