Skip to content

Commit

Permalink
Fixes #37416 - assign templates for new Debian/Suse OSs
Browse files Browse the repository at this point in the history
  • Loading branch information
sbernhard authored and wbclark committed Jun 25, 2024
1 parent 16440c3 commit bc07be6
Show file tree
Hide file tree
Showing 2 changed files with 192 additions and 16 deletions.
100 changes: 84 additions & 16 deletions app/models/katello/concerns/operatingsystem_extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,101 @@ module OperatingsystemExtensions
REDHAT_ATOMIC_HOST_DISTRO_NAME = "Red Hat Enterprise Linux Atomic Host".freeze
REDHAT_ATOMIC_HOST_OS = "RedHat_Enterprise_Linux_Atomic_Host".freeze

DEBIAN_DEFAULT_PROVISIONING_TEMPLATE = "Preseed default %{template_kind_name}".freeze
DEBIAN_DEFAULT_PTABLE = "Preseed default".freeze

SUSE_DEFAULT_PROVISIONING_TEMPLATE = "AutoYaST default %{template_kind_name}".freeze
SUSE_DEFAULT_PTABLE = "AutoYaST entire SCSI disk".freeze

included do
after_create :assign_templates!
before_create :set_atomic_attributes, :if => proc { |os| os.name == ::Operatingsystem::REDHAT_ATOMIC_HOST_OS }
end

def assign_templates!
# Automatically assign default templates
if self.family == 'Redhat'
TemplateKind.all.each do |kind|
if name == ::Operatingsystem::REDHAT_ATOMIC_HOST_OS && kind.name == "provision"
provisioning_template_name = Setting["katello_default_atomic_provision"]
else
provisioning_template_name = Setting["katello_default_#{kind.name}"]
end
def find_related_os
Operatingsystem.unscoped.where(name: self.name).order(major: :desc, minor: :desc).where.not(id: self.id)
end

def assign_related_os_templates
all_related_os = find_related_os
return false if all_related_os.nil?

boot_loader_template_kinds = TemplateKind.where(name: ["PXELinux", "PXEGrub", "PXEGrub2", "iPXE"]).pluck(:id)
provision_template_kinds = TemplateKind.where(name: ["provision", "finish"]).pluck(:id)

if (template = ProvisioningTemplate.unscoped.find_by_name(provisioning_template_name))
provisioning_templates << template unless provisioning_templates.include?(template)
if OsDefaultTemplate.where(:template_kind_id => kind.id, :operatingsystem_id => id).empty?
OsDefaultTemplate.create(:template_kind_id => kind.id, :provisioning_template_id => template.id, :operatingsystem_id => id)
end
all_related_os.each do |related_os|
next if related_os.provisioning_templates.empty? || related_os.ptables.empty?
next if related_os.provisioning_templates.where(template_kind_id: boot_loader_template_kinds).size == 0
next if related_os.provisioning_templates.where(template_kind_id: provision_template_kinds).size == 0

Rails.logger.info "Using operating system #{related_os.name} (major: #{related_os.major}, minor: #{related_os.minor}) " \
"as a template source for the new OS #{name} (major: #{major}, minor: #{minor})."

related_os.ptables.each do |ptable|
ptables << ptable unless ptables.include?(ptable)
end

related_os.provisioning_templates.each do |template|
provisioning_templates << template unless provisioning_templates.include?(template)
OsDefaultTemplate.where(:operatingsystem_id => related_os.id, :provisioning_template_id => template.id).each do |os_default_temp|
OsDefaultTemplate.create(:template_kind_id => os_default_temp.template_kind_id,
:provisioning_template_id => os_default_temp.provisioning_template_id,
:operatingsystem_id => id)
end
end
return true
end
false
end

def provisioning_template_name_for_os(template_kind_name)
case self.family
when 'Redhat'
if name == ::Operatingsystem::REDHAT_ATOMIC_HOST_OS && template_kind_name == "provision"
Setting["katello_default_atomic_provision"]
else
Setting["katello_default_#{template_kind_name}"]
end
when 'Debian'
format(DEBIAN_DEFAULT_PROVISIONING_TEMPLATE, template_kind_name: template_kind_name)
when 'Suse'
format(SUSE_DEFAULT_PROVISIONING_TEMPLATE, template_kind_name: template_kind_name)
end
end

if (ptable = Ptable.unscoped.find_by_name(Setting["katello_default_ptable"]))
ptables << ptable unless ptables.include?(ptable)
def partition_table_name_for_os
case self.family
when 'Redhat'
Setting["katello_default_ptable"]
when 'Debian'
DEBIAN_DEFAULT_PTABLE
when 'Suse'
SUSE_DEFAULT_PTABLE
end
end

def assign_templates!
if [ 'Suse', 'Debian' ].include?(self.family)
return if assign_related_os_templates
end

# Automatically assign default templates
TemplateKind.all.each do |kind|
provisioning_template_name = provisioning_template_name_for_os(kind.name)
next if provisioning_template_name.nil?
if (template = ProvisioningTemplate.unscoped.find_by_name(provisioning_template_name))
provisioning_templates << template unless provisioning_templates.include?(template)
if OsDefaultTemplate.where(:template_kind_id => kind.id, :operatingsystem_id => id).empty?
OsDefaultTemplate.create(:template_kind_id => kind.id, :provisioning_template_id => template.id, :operatingsystem_id => id)
end
end
end

partition_table_name = partition_table_name_for_os
return if partition_table_name.nil?
if (ptable = Ptable.unscoped.find_by_name(partition_table_name))
ptables << ptable unless ptables.include?(ptable)
end
end

def set_atomic_attributes
Expand Down
108 changes: 108 additions & 0 deletions test/models/concerns/operatingsystem_extensions_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,113 @@ def test_assign_template_for_atomic
assert_equal "x86_64", os.architectures.first.name
assert_equal "#{::Operatingsystem::REDHAT_ATOMIC_HOST_DISTRO_NAME} 7.3", os.description
end

context 'use predefined templates for debian' do
setup do
template_name = format(::Operatingsystem::DEBIAN_DEFAULT_PROVISIONING_TEMPLATE, template_kind_name: 'PXELinux')
@provisioning_template = FactoryBot.create(:provisioning_template, :template_kind => TemplateKind.find_by_name(:PXELinux), :name => template_name)
@ptable = FactoryBot.create(:ptable, :ubuntu, :name => ::Operatingsystem::DEBIAN_DEFAULT_PTABLE)
end

def test_assign_template_from_predefined
ProvisioningTemplate.stubs(:find_by_name).returns(@provisioning_template)
Ptable.stubs(:find_by_name).returns(@ptable)

# if find_related_os returns nil, it should use the default template
Operatingsystem.any_instance.stubs(:find_related_os).returns(nil)

os_attributes = {:major => "22.04", :minor => "", :name => 'Ubuntu', :release_name => 'jammy'}
os = Operatingsystem.create!(os_attributes)

assert ::OsDefaultTemplate.where(:template_kind_id => ::TemplateKind.find_by_name('PXELinux').id,
:provisioning_template_id => @provisioning_template.id,
:operatingsystem_id => os.id).any?
assert_includes os.ptables, @ptable
end
end

context 'use find_relates_os templates for sles' do
setup do
template_name1 = format(::Operatingsystem::SUSE_DEFAULT_PROVISIONING_TEMPLATE, template_kind_name: 'PXELinux')
@provisioning_template1 = FactoryBot.create(:provisioning_template, :template_kind => TemplateKind.find_by_name(:PXELinux), :name => template_name1)
template_name2 = format(::Operatingsystem::SUSE_DEFAULT_PROVISIONING_TEMPLATE, template_kind_name: 'provision')
@provisioning_template2 = FactoryBot.create(:provisioning_template, :template_kind => TemplateKind.find_by_name(:provision), :name => template_name2)
template_name3 = format(::Operatingsystem::SUSE_DEFAULT_PROVISIONING_TEMPLATE, template_kind_name: 'host_init_config')
@provisioning_template3 = FactoryBot.create(:provisioning_template, :template_kind => TemplateKind.find_by_name(:host_init_config), :name => template_name3)
@ptable = FactoryBot.create(:ptable, :suse, :name => ::Operatingsystem::SUSE_DEFAULT_PTABLE)

os_attributes1 = {:major => "15", :minor => "1", :name => 'SLES' }
@os1 = Operatingsystem.create!(os_attributes1)
@os1.ptables = [@ptable]
@os1.provisioning_templates = [@provisioning_template1, @provisioning_template2]
@os1.save!
end

def test_assign_template_from_related_first
os_attributes_new = {:major => "15", :minor => "2", :name => 'SLES' }
Rails.logger.expects(:info).with("Using operating system #{@os1.name} (major: #{@os1.major}, minor: #{@os1.minor}) " \
"as a template source for the new OS #{os_attributes_new[:name]} " \
"(major: #{os_attributes_new[:major]}, minor: #{os_attributes_new[:minor]}).")
os_new = Operatingsystem.create!(os_attributes_new)
assert_equal "2", os_new.minor
assert_equal "15", os_new.major
assert ::OsDefaultTemplate.where(:template_kind_id => ::TemplateKind.find_by_name('PXELinux').id,
:provisioning_template_id => @provisioning_template1.id,
:operatingsystem_id => os_new.id).any?
assert ::OsDefaultTemplate.where(:template_kind_id => ::TemplateKind.find_by_name('provision').id,
:provisioning_template_id => @provisioning_template2.id,
:operatingsystem_id => os_new.id).any?
assert_includes os_new.ptables, @ptable
end

def test_assign_template_from_related_second
# This is the latest OS with higher minor version but no ptables is assigned -> it need to use @os1 as a template
os_attributes2 = {:major => "15", :minor => "2", :name => 'SLES' }
os2 = Operatingsystem.create!(os_attributes2)
os2.ptables = []
os2.provisioning_templates = [@provisioning_template1, @provisioning_template2]
os2.save!

os_attributes_new = {:major => "15", :minor => "3", :name => 'SLES' }
Rails.logger.expects(:info).with("Using operating system #{@os1.name} (major: #{@os1.major}, minor: #{@os1.minor}) " \
"as a template source for the new OS #{os_attributes_new[:name]} " \
"(major: #{os_attributes_new[:major]}, minor: #{os_attributes_new[:minor]}).")
os_new = Operatingsystem.create!(os_attributes_new)
assert_equal "3", os_new.minor
assert_equal "15", os_new.major
assert ::OsDefaultTemplate.where(:template_kind_id => ::TemplateKind.find_by_name('PXELinux').id,
:provisioning_template_id => @provisioning_template1.id,
:operatingsystem_id => os_new.id).any?
assert ::OsDefaultTemplate.where(:template_kind_id => ::TemplateKind.find_by_name('provision').id,
:provisioning_template_id => @provisioning_template2.id,
:operatingsystem_id => os_new.id).any?
assert_includes os_new.ptables, @ptable
end

def test_assign_template_from_related_third
# This is the latest OS with higher minor version but specific templates are not assigned -> it need to use @os1 as a template
os_attributes2 = {:major => "15", :minor => "2", :name => 'SLES' }
os2 = Operatingsystem.create!(os_attributes2)
os2.ptables = [@ptable]
os2.provisioning_templates = [@provisioning_template3]
os2.save!

os_attributes_new = {:major => "15", :minor => "3", :name => 'SLES' }
Rails.logger.expects(:info).with("Using operating system #{@os1.name} (major: #{@os1.major}, minor: #{@os1.minor}) " \
"as a template source for the new OS #{os_attributes_new[:name]} " \
"(major: #{os_attributes_new[:major]}, minor: #{os_attributes_new[:minor]}).")
os_new = Operatingsystem.create!(os_attributes_new)
assert_equal "3", os_new.minor
assert_equal "15", os_new.major
assert ::OsDefaultTemplate.where(:template_kind_id => ::TemplateKind.find_by_name('PXELinux').id,
:provisioning_template_id => @provisioning_template1.id,
:operatingsystem_id => os_new.id).any?
assert ::OsDefaultTemplate.where(:template_kind_id => ::TemplateKind.find_by_name('provision').id,
:provisioning_template_id => @provisioning_template2.id,
:operatingsystem_id => os_new.id).any?
assert @os1.ptables.pluck(:name).all? { |t| os_new.ptables.pluck(:name).include?(t) }
assert_includes os_new.ptables, @ptable
end
end
end
end

0 comments on commit bc07be6

Please sign in to comment.