From be5fe6464a861834aefa2b9eee504c1755253328 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Wed, 20 Sep 2023 13:26:23 +0200 Subject: [PATCH 01/30] Avoid build error on not used architectures. --- package/yast2-sap-ha.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package/yast2-sap-ha.spec b/package/yast2-sap-ha.spec index 9965fb6..0cb25bb 100644 --- a/package/yast2-sap-ha.spec +++ b/package/yast2-sap-ha.spec @@ -40,7 +40,9 @@ Requires: xdg-utils Requires: expect Requires: firewalld Requires: openssh +%ifarch x86_64 ppc64le Requires: HANA-Firewall >= 2.0.3 +%endif Requires: util-linux Requires: SAPHanaSR Requires: kmod From 4fa7df7ec787e05519ca971714fd5fcccba491d4 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Wed, 20 Sep 2023 13:28:44 +0200 Subject: [PATCH 02/30] Fix package requirement for yast2-cluster --- package/yast2-sap-ha.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/yast2-sap-ha.spec b/package/yast2-sap-ha.spec index 0cb25bb..9c81ac1 100644 --- a/package/yast2-sap-ha.spec +++ b/package/yast2-sap-ha.spec @@ -31,7 +31,7 @@ Requires: csync2 Requires: hawk2 Requires: pacemaker Requires: yast2 -Requires: yast2-cluster >= 4.3.8 +Requires: yast2-cluster >= 4.4.4 Requires: yast2-ruby-bindings Requires: yast2-ntp-client # for opening URLs From 938db721009aa2fdf7f24e9738bc45d9f88d0cb5 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Fri, 27 Oct 2023 16:53:33 +0200 Subject: [PATCH 03/30] yast2-sap-ha does not set global_allocation_limit for non productive database (bsc#1216651) --- src/data/sap_ha/GLOBAL_INI_NON_PROD.erb | 2 ++ src/data/sap_ha/GLOBAL_INI_SUS_COSTOPT.erb | 2 +- src/lib/sap_ha/configuration/hana.rb | 24 ++++++++++++++-------- src/lib/sap_ha/wizard/hana_page.rb | 6 ++++-- 4 files changed, 22 insertions(+), 12 deletions(-) create mode 100644 src/data/sap_ha/GLOBAL_INI_NON_PROD.erb diff --git a/src/data/sap_ha/GLOBAL_INI_NON_PROD.erb b/src/data/sap_ha/GLOBAL_INI_NON_PROD.erb new file mode 100644 index 0000000..333df6e --- /dev/null +++ b/src/data/sap_ha/GLOBAL_INI_NON_PROD.erb @@ -0,0 +1,2 @@ +[memorymanager] +global_allocation_limit = <%= @production_constraints[:global_alloc_limit_non] -%> diff --git a/src/data/sap_ha/GLOBAL_INI_SUS_COSTOPT.erb b/src/data/sap_ha/GLOBAL_INI_SUS_COSTOPT.erb index a9e6414..b35ce3d 100644 --- a/src/data/sap_ha/GLOBAL_INI_SUS_COSTOPT.erb +++ b/src/data/sap_ha/GLOBAL_INI_SUS_COSTOPT.erb @@ -1,5 +1,5 @@ [memorymanager] -global_allocation_limit = <%= @production_constraints[:global_alloc_limit] -%> +global_allocation_limit = <%= @production_constraints[:global_alloc_limit_prod] -%> [system_replication] preload_column_tables = <%= @production_constraints[:preload_column_tables] -%> diff --git a/src/lib/sap_ha/configuration/hana.rb b/src/lib/sap_ha/configuration/hana.rb index 7565928..f8208f0 100644 --- a/src/lib/sap_ha/configuration/hana.rb +++ b/src/lib/sap_ha/configuration/hana.rb @@ -95,8 +95,10 @@ def initialize(global_config) def additional_instance=(value) @additional_instance = value return unless value + @prefer_takeover = false @production_constraints = { - global_alloc_limit: "0", + global_alloc_limit_prod: "0", + global_alloc_limit_non: "0", preload_column_tables: "false" } end @@ -195,7 +197,8 @@ def hana_backup_validator(check, hash) def production_constraints_validation(check, hash) check.element_in_set(hash[:preload_column_tables], ["true", "false"], "The field must contain a boolean value: 'true' or 'false'", "Preload column tables") - check.nonneg_integer(hash[:global_alloc_limit], "Global allocation limit") + check.not_equal(hash[:global_alloc_limit_prod], 0, "Global allocation limit production system must be adapted.") + check.not_equal(hash[:global_alloc_limit_non], 0, "Global allocation limit of non production system must be adapted.") end # Validator for the non-production instance constraints popup @@ -294,27 +297,30 @@ def adapt_sudoers # Activates all necessary plugins based on role an scenario def adjust_global_ini(role) # SAPHanaSR is needed on all nodes - add_plugin_to_global_ini("SAPHANA_SR") + add_plugin_to_global_ini("SAPHANA_SR", @system_id) if @additional_instance # cost optimized - add_plugin_to_global_ini("SUS_COSTOPT") if role != :master + add_plugin_to_global_ini("SUS_COSTOPT", @system_id) if role != :master + add_plugin_to_global_ini("NON_PROD", @np_system_id) if role != :master + command = ["hdbnsutil", "-reloadHADRProviders"] + out, status = su_exec_outerr_status("#{@system_id.downcase}adm", *command) else # performance optimized - add_plugin_to_global_ini("SUS_CHKSRV") - add_plugin_to_global_ini("SUS_TKOVER") + add_plugin_to_global_ini("SUS_CHKSRV", @system_id) + add_plugin_to_global_ini("SUS_TKOVER", @system_id) end command = ["hdbnsutil", "-reloadHADRProviders"] out, status = su_exec_outerr_status("#{@system_id.downcase}adm", *command) end # Activates the plugin in global ini - def add_plugin_to_global_ini(plugin) + def add_plugin_to_global_ini(plugin, sid) sr_path = Helpers.data_file_path("GLOBAL_INI_#{plugin}") if File.exist?("#{sr_path}.erb") sr_path = Helpers.write_var_file(plugin, Helpers.render_template("GLOBAL_INI_#{plugin}.erb", binding)) end - command = ["/usr/sbin/SAPHanaSR-manageProvider", "--add", "--sid", @system_id, sr_path] - out, status = su_exec_outerr_status("#{@system_id.downcase}adm", *command) + command = ["/usr/sbin/SAPHanaSR-manageProvider", "--add", "--sid", sid, sr_path] + out, status = su_exec_outerr_status("#{sid.downcase}adm", *command) end end end diff --git a/src/lib/sap_ha/wizard/hana_page.rb b/src/lib/sap_ha/wizard/hana_page.rb index eed77fb..214344f 100644 --- a/src/lib/sap_ha/wizard/hana_page.rb +++ b/src/lib/sap_ha/wizard/hana_page.rb @@ -142,8 +142,10 @@ def hana_production_constraints_popup(values) base_popup( "Production system constraints", @my_model.method(:production_constraints_validation), - MinWidth(20, InputField(Id(:global_alloc_limit), "Global &allocation limit (in MB):", - values[:global_alloc_limit] || "")), + MinWidth(20, InputField(Id(:global_alloc_limit_prod), "Productive DB global allocation limit (in MB):", + values[:global_alloc_limit_prod] || "")), + MinWidth(20, InputField(Id(:global_alloc_limit_non), "Non-productive DB global allocation limit (in MB):", + values[:global_alloc_limit_non] || "")), MinWidth(20, InputField(Id(:preload_column_tables), "&Preload column tables:", values[:preload_column_tables] || "")) ) From 8d04938202dab982b49e2cab278397f185dd3326 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Mon, 30 Oct 2023 20:20:39 +0100 Subject: [PATCH 04/30] Use the right system id to configure global.ini for non productive db. --- src/lib/sap_ha/configuration/hana.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/sap_ha/configuration/hana.rb b/src/lib/sap_ha/configuration/hana.rb index f8208f0..ede437c 100644 --- a/src/lib/sap_ha/configuration/hana.rb +++ b/src/lib/sap_ha/configuration/hana.rb @@ -303,7 +303,7 @@ def adjust_global_ini(role) add_plugin_to_global_ini("SUS_COSTOPT", @system_id) if role != :master add_plugin_to_global_ini("NON_PROD", @np_system_id) if role != :master command = ["hdbnsutil", "-reloadHADRProviders"] - out, status = su_exec_outerr_status("#{@system_id.downcase}adm", *command) + out, status = su_exec_outerr_status("#{@np_system_id.downcase}adm", *command) else # performance optimized add_plugin_to_global_ini("SUS_CHKSRV", @system_id) From e7aac7946bd65730926f6b22aa950280f4189fc4 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Thu, 2 Nov 2023 11:04:34 +0100 Subject: [PATCH 05/30] yast2-sap-ha wizard terminates abruptly when save configuration option is selected post configuration bsc#1214603 --- src/lib/sap_ha/wizard/base_wizard_page.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lib/sap_ha/wizard/base_wizard_page.rb b/src/lib/sap_ha/wizard/base_wizard_page.rb index f1fec45..9ec8640 100644 --- a/src/lib/sap_ha/wizard/base_wizard_page.rb +++ b/src/lib/sap_ha/wizard/base_wizard_page.rb @@ -250,8 +250,10 @@ def base_popup(message, validator, *widgets) Yast::UI.CloseDialog return parameters when :cancel - Yast::UI.CloseDialog - return nil + if Yast::Popup.YesNo(_("Do you realy want to abort?")) + Yast::UI.CloseDialog + return nil + end end end end From effb245a311dd65ad5e2ba6e0b6616688c1c3409 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Thu, 2 Nov 2023 11:10:24 +0100 Subject: [PATCH 06/30] New version --- package/yast2-sap-ha.changes | 9 +++++++++ package/yast2-sap-ha.spec | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/package/yast2-sap-ha.changes b/package/yast2-sap-ha.changes index 320ce96..e4d610c 100644 --- a/package/yast2-sap-ha.changes +++ b/package/yast2-sap-ha.changes @@ -1,3 +1,12 @@ +------------------------------------------------------------------- +Thu Nov 2 10:05:10 UTC 2023 - Peter Varkoly + +- yast2-sap-ha wizard terminates abruptly when save configuration option + is selected post configuration (bsc#1214603) +- yast2-sap-ha does not set global_allocation_limit for non productive database + (bsc#1216651) +- 4.4.6 + ------------------------------------------------------------------- Mon Aug 7 05:13:47 UTC 2023 - Peter Varkoly diff --git a/package/yast2-sap-ha.spec b/package/yast2-sap-ha.spec index 9c81ac1..ed09a35 100644 --- a/package/yast2-sap-ha.spec +++ b/package/yast2-sap-ha.spec @@ -17,7 +17,7 @@ Name: yast2-sap-ha -Version: 4.4.5 +Version: 4.4.6 Release: 0 BuildArch: noarch Source0: %{name}-%{version}.tar.bz2 From 348765142e0ff16efc4675b06a62aef5bb28e363 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Wed, 8 Nov 2023 09:23:54 +0100 Subject: [PATCH 07/30] Add textdomain --- src/lib/sap_ha/wizard/base_wizard_page.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/sap_ha/wizard/base_wizard_page.rb b/src/lib/sap_ha/wizard/base_wizard_page.rb index 9ec8640..9450963 100644 --- a/src/lib/sap_ha/wizard/base_wizard_page.rb +++ b/src/lib/sap_ha/wizard/base_wizard_page.rb @@ -44,6 +44,7 @@ class BaseWizardPage # Initialize the Wizard page def initialize(model) + textdomain "hana-ha" log.debug "--- #{self.class}.#{__callee__} ---" @model = model end From 687488c964fee78d2d2b90ac02ebe50b258f547e Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Thu, 9 Nov 2023 09:18:27 +0100 Subject: [PATCH 08/30] Refresh only the proposal to avoid rewriting the settings in the read configuration. Refresh the timestamp when writting the configuration --- src/lib/sap_ha/configuration.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/sap_ha/configuration.rb b/src/lib/sap_ha/configuration.rb index 7eca746..6629625 100644 --- a/src/lib/sap_ha/configuration.rb +++ b/src/lib/sap_ha/configuration.rb @@ -94,7 +94,7 @@ def initialize(role = :master) # loading an old configuration to detect new hardware. def refresh_all_proposals @watchdog.refresh_proposals - @fencing.read_system + @fencing.refresh_proposals end # Product ID setter. Raises an ScenarioNotFoundException if the ID was not found @@ -233,6 +233,7 @@ def collect_log def write_config log.debug "--- called #{self.class}.#{__callee__} ---" + @timestamp = Time.now SapHA::Helpers.write_var_file("configuration.yml", dump(false, true), timestamp: @timestamp) end From 96c1dd4033dd34da8be9fe5f64ea4d58994e9d7f Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Thu, 9 Nov 2023 09:24:53 +0100 Subject: [PATCH 09/30] Increase debug --- src/clients/sap_ha.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/clients/sap_ha.rb b/src/clients/sap_ha.rb index a0efbd1..834d925 100644 --- a/src/clients/sap_ha.rb +++ b/src/clients/sap_ha.rb @@ -312,7 +312,9 @@ def scenario_selection log.debug "--- called #{self.class}.#{__callee__}:: ret is #{selection.class} ---" if selection.is_a?(SapHA::HAConfiguration) @config = selection + log.debug "-- @config #{@config.to_yaml}" @config.refresh_all_proposals + log.debug "-- @config after refresh #{@config.to_yaml}" return :next end selection From 605863fadc023ada5b7143267a6c006581c08fe1 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Thu, 9 Nov 2023 09:26:01 +0100 Subject: [PATCH 10/30] Increase debug infos refresh_proposals must not be private. --- src/lib/sap_ha/configuration/fencing.rb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/lib/sap_ha/configuration/fencing.rb b/src/lib/sap_ha/configuration/fencing.rb index 9b6cd2c..0d28812 100644 --- a/src/lib/sap_ha/configuration/fencing.rb +++ b/src/lib/sap_ha/configuration/fencing.rb @@ -28,7 +28,7 @@ module Configuration # Fencing configuration class Fencing < BaseConfig attr_reader :proposals, :sysconfig - attr_accessor :sbd_options, :sbd_delayed_start + attr_accessor :sbd_options, :sbd_delayed_start, :devices include Yast::UIShortcuts include Yast::Logger @@ -83,7 +83,9 @@ def list_items(key) end def table_items - @devices.each_with_index.map { |e, i| Item(Id(i), (i + 1).to_s, e) } + de_items = @devices.each_with_index.map { |e, i| Item(Id(i), (i + 1).to_s, e) } + log.debug "table_items #{@devices}" + return de_items end def popup_validator(check, dev_path) @@ -144,8 +146,11 @@ def apply(role) flag end - private + def refresh_proposals + @proposals = SapHA::System::Local.block_devices + end + private def handle_sysconfig handle = ->(sett, default) { (sett.nil? || sett.empty?) ? default : sett } @devices = handle.call(@sysconfig[:device], "").split(";") @@ -154,9 +159,6 @@ def handle_sysconfig true end - def refresh_proposals - @proposals = SapHA::System::Local.block_devices - end end end end From 5ece3bc42898dbdcb3757b49aca770463384bad7 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Thu, 9 Nov 2023 09:26:53 +0100 Subject: [PATCH 11/30] Fix checking global alloc limit. The value is given in string. --- src/lib/sap_ha/configuration/hana.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/sap_ha/configuration/hana.rb b/src/lib/sap_ha/configuration/hana.rb index ede437c..52b5652 100644 --- a/src/lib/sap_ha/configuration/hana.rb +++ b/src/lib/sap_ha/configuration/hana.rb @@ -97,8 +97,8 @@ def additional_instance=(value) return unless value @prefer_takeover = false @production_constraints = { - global_alloc_limit_prod: "0", - global_alloc_limit_non: "0", + global_alloc_limit_prod: "0", + global_alloc_limit_non: "0", preload_column_tables: "false" } end @@ -197,8 +197,8 @@ def hana_backup_validator(check, hash) def production_constraints_validation(check, hash) check.element_in_set(hash[:preload_column_tables], ["true", "false"], "The field must contain a boolean value: 'true' or 'false'", "Preload column tables") - check.not_equal(hash[:global_alloc_limit_prod], 0, "Global allocation limit production system must be adapted.") - check.not_equal(hash[:global_alloc_limit_non], 0, "Global allocation limit of non production system must be adapted.") + check.not_equal(hash[:global_alloc_limit_prod], 0.to_s, "Global allocation limit production system must be adapted.") + check.not_equal(hash[:global_alloc_limit_non], 0.to_s, "Global allocation limit of non production system must be adapted.") end # Validator for the non-production instance constraints popup From 7eba7005f60f4e17c2a04fa5d2234a2968d4c908 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Thu, 9 Nov 2023 09:29:21 +0100 Subject: [PATCH 12/30] Fix text indentation --- src/lib/sap_ha/semantic_checks.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/sap_ha/semantic_checks.rb b/src/lib/sap_ha/semantic_checks.rb index a03dbce..d53a334 100644 --- a/src/lib/sap_ha/semantic_checks.rb +++ b/src/lib/sap_ha/semantic_checks.rb @@ -284,7 +284,7 @@ def check(verbosity) false else true - end + end transaction_begin yield self return transaction_end if verbosity == :verbose From 1f8d173c697bddfe578f0a69853101641dde62a2 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Thu, 9 Nov 2023 09:30:28 +0100 Subject: [PATCH 13/30] Fix bsc#1214603 in the right function --- src/lib/sap_ha/wizard/base_wizard_page.rb | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/lib/sap_ha/wizard/base_wizard_page.rb b/src/lib/sap_ha/wizard/base_wizard_page.rb index 9450963..98596da 100644 --- a/src/lib/sap_ha/wizard/base_wizard_page.rb +++ b/src/lib/sap_ha/wizard/base_wizard_page.rb @@ -105,8 +105,12 @@ def main_loop case input # TODO: return only :abort, :cancel and :back from here. If the page needs anything else, # it should redefine the main_loop - when :abort, :back, :cancel, :join_cluster - @model.write_config if input == :abort || input == :cancel + when :abort, :cancel + if Yast::Popup.YesNo(_("Do you realy want to abort?")) + @model.write_config + return input + end + when :back, :join_cluster update_model return input when :next, :summary @@ -240,8 +244,9 @@ def base_popup(message, validator, *widgets) end.params[0] parameters[id] = Yast::UI.QueryWidget(Id(id), :Value) end - log.debug "--- #{self.class}.#{__callee__} popup parameters: #{parameters} ---" + log.debug "--- #{self.class}.#{__callee__} popup parameters: #{parameters} --- #{validator.class} -- #{@model.no_validators}" if validator && !@model.no_validators + log.debug "validator called" ret = SemanticChecks.instance.check_popup(validator, parameters) unless ret.empty? show_dialog_errors(ret) @@ -251,10 +256,8 @@ def base_popup(message, validator, *widgets) Yast::UI.CloseDialog return parameters when :cancel - if Yast::Popup.YesNo(_("Do you realy want to abort?")) - Yast::UI.CloseDialog - return nil - end + Yast::UI.CloseDialog + return nil end end end From f0122c3b2138fcd85e1c87ab2c19ac940f1130fc Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Thu, 9 Nov 2023 09:34:04 +0100 Subject: [PATCH 14/30] Complete changes. --- package/yast2-sap-ha.changes | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package/yast2-sap-ha.changes b/package/yast2-sap-ha.changes index e4d610c..2bd6e28 100644 --- a/package/yast2-sap-ha.changes +++ b/package/yast2-sap-ha.changes @@ -1,10 +1,11 @@ ------------------------------------------------------------------- -Thu Nov 2 10:05:10 UTC 2023 - Peter Varkoly +Thu Nov 9 08:31:53 UTC 2023 - Peter Varkoly - yast2-sap-ha wizard terminates abruptly when save configuration option is selected post configuration (bsc#1214603) - yast2-sap-ha does not set global_allocation_limit for non productive database (bsc#1216651) +- Take care that the read values from the saved configuration will not be overridden - 4.4.6 ------------------------------------------------------------------- From 035afc15e2c0ff4b594dc0adc0078bf4660fb4e8 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Thu, 16 Nov 2023 16:11:37 +0100 Subject: [PATCH 15/30] Fix parameter for sysconfig write. --- src/lib/sap_ha/configuration/hana.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/sap_ha/configuration/hana.rb b/src/lib/sap_ha/configuration/hana.rb index 52b5652..69c6daa 100644 --- a/src/lib/sap_ha/configuration/hana.rb +++ b/src/lib/sap_ha/configuration/hana.rb @@ -271,7 +271,7 @@ def config_firewall(role) @nlog.info("Firewall will be configured for HANA services.") instances = Yast::SCR.Read(Yast::Path.new(".sysconfig.hana-firewall.HANA_INSTANCE_NUMBERS")).split instances << @instance - Yast::SCR.Write(Yast::Path.new(".sysconfig.hana-firewall.HANA_INSTANCE_NUMBERS"), instances) + Yast::SCR.Write(Yast::Path.new(".sysconfig.hana-firewall.HANA_INSTANCE_NUMBERS"), instances.join(" ")) Yast::SCR.Write(Yast::Path.new(".sysconfig.hana-firewall"), nil) _s = exec_status("/usr/sbin/hana-firewall", "generate-firewalld-services") _s = exec_status("/usr/bin/firewall-cmd", "--reload") From 0d2060de96c9607e20a0d32c893c5615b884e2a7 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Thu, 16 Nov 2023 16:24:49 +0100 Subject: [PATCH 16/30] Check if HANA db with given SID is installed. --- src/lib/sap_ha/configuration/hana.rb | 2 ++ src/lib/sap_ha/semantic_checks.rb | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/lib/sap_ha/configuration/hana.rb b/src/lib/sap_ha/configuration/hana.rb index 69c6daa..55a5a81 100644 --- a/src/lib/sap_ha/configuration/hana.rb +++ b/src/lib/sap_ha/configuration/hana.rb @@ -113,6 +113,7 @@ def configured? def validate(verbosity = :verbose) SemanticChecks.instance.check(verbosity) do |check| + check.hana_is_installed(@system_id) check.ipv4(@virtual_ip, "Virtual IP") check.nonneg_integer(@virtual_ip_mask, "Virtual IP mask") check.integer_in_range(@virtual_ip_mask, 1, 32, "CIDR mask has to be between 1 and 32.", @@ -139,6 +140,7 @@ def validate(verbosity = :verbose) "There is no such HANA user store key detected.", "Secure store key") end if @additional_instance + check.hana_is_installed(@np_system_id) check.sap_instance_number(@np_instance, nil, "Non-Production Instance Number") check.sap_sid(@np_system_id, nil, "Non-Production System ID") check.not_equal(@instance, @np_instance, "SAP HANA instance numbers should not collide", diff --git a/src/lib/sap_ha/semantic_checks.rb b/src/lib/sap_ha/semantic_checks.rb index d53a334..b5da086 100644 --- a/src/lib/sap_ha/semantic_checks.rb +++ b/src/lib/sap_ha/semantic_checks.rb @@ -264,6 +264,18 @@ def non_empty_string(value, message, field_name, hide_value = false) report_error(flag, message || "The value must be a non-empty string", field_name, shown_value) end + # Check if a HANA db with given sid is installed + def hana_is_installed(value, message = "", field_name = "SID", hide_value = false) + message = "No SAP HANA is installed with given SID." if message.empty? + begin + flag = File::Stat.new("/usr/sap/" + value.upcase).dir? + rescue StandardError + flag = false + end + log.error "hana installed: #{value}.blockdev? = #{flag}" + report_error(flag, msg, field_name, value) + end + # Check if string is a block device # @param value [String] device path def block_device(value, field_name) From 6c9b9e47bca70a2be6575dc262bb82b99d8666a6 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Fri, 17 Nov 2023 08:16:47 +0100 Subject: [PATCH 17/30] Do not check if HANA is installed in the test envinroment. --- src/lib/sap_ha/semantic_checks.rb | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/lib/sap_ha/semantic_checks.rb b/src/lib/sap_ha/semantic_checks.rb index b5da086..f54e83b 100644 --- a/src/lib/sap_ha/semantic_checks.rb +++ b/src/lib/sap_ha/semantic_checks.rb @@ -50,6 +50,7 @@ def initialize @errors = [] @checks_passed = true @silent = true + @test = !ENV["Y2DIR"].nil? end # Check if the string is a valid IPv4 address @@ -74,8 +75,8 @@ def ipv4_netmask(value, field_name = "") # @param field_name [String] name of the field in the form def ipv4_multicast(value, field_name = "") flag = Yast::IP.Check4(value) && value.start_with?("239.") - msg = "A valid IPv4 multicast address should belong to the 239.* network." - report_error(flag, msg, field_name, value) + message = "A valid IPv4 multicast address should belong to the 239.* network." + report_error(flag, message, field_name, value) end # Check if the IP belongs to the specified network given along with a CIDR netmask @@ -88,8 +89,8 @@ def ipv4_in_network_cidr(ip, network, field_name = "") rescue StandardError flag = false end - msg = "IP address has to belong to the network #{network}." - report_error(flag, msg, field_name, ip) + message = "IP address has to belong to the network #{network}." + report_error(flag, message, field_name, ip) end # Check if the provided IPs belong to the network @@ -122,14 +123,14 @@ def hostname(value, field_name = "") # @param field_name [String] name of the field in the form def port(value, field_name = "") max_port_number = 65_535 - msg = "The port number must be in between 1 and #{max_port_number}." + message = "The port number must be in between 1 and #{max_port_number}." begin portn = Integer(value) flag = 1 <= portn && portn <= 65_535 rescue ArgumentError, TypeError - return report_error(false, msg, field_name, value) + return report_error(false, message, field_name, value) end - report_error(flag, msg, field_name, value) + report_error(flag, message, field_name, value) end # Check if the provided value is a non-negative integer @@ -268,25 +269,25 @@ def non_empty_string(value, message, field_name, hide_value = false) def hana_is_installed(value, message = "", field_name = "SID", hide_value = false) message = "No SAP HANA is installed with given SID." if message.empty? begin - flag = File::Stat.new("/usr/sap/" + value.upcase).dir? + flag = File.directory?("/usr/sap/" + value.upcase) rescue StandardError flag = false end - log.error "hana installed: #{value}.blockdev? = #{flag}" - report_error(flag, msg, field_name, value) + flag = true if @test + report_error(flag, message, field_name, value) end # Check if string is a block device # @param value [String] device path def block_device(value, field_name) - msg = "The provided path does not point to a block device." + message = "The provided path does not point to a block device." begin flag = File::Stat.new(value).blockdev? rescue StandardError flag = false end log.error "BLK: #{value}.blockdev? = #{flag}" - report_error(flag, msg, field_name, value) + report_error(flag, message, field_name, value) end # Start a transactional check From b905880419be6861cb719a03692e2f72b55e422b Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Fri, 17 Nov 2023 10:54:46 +0100 Subject: [PATCH 18/30] Check if the HANA systems with the given SID are installed on the required system --- src/lib/sap_ha/configuration/cluster.rb | 7 ++++++ src/lib/sap_ha/configuration/hana.rb | 4 ++-- src/lib/sap_ha/semantic_checks.rb | 30 +++++++++++++++++-------- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/lib/sap_ha/configuration/cluster.rb b/src/lib/sap_ha/configuration/cluster.rb index 742e994..306bd28 100644 --- a/src/lib/sap_ha/configuration/cluster.rb +++ b/src/lib/sap_ha/configuration/cluster.rb @@ -247,6 +247,13 @@ def other_nodes ips end + # return all IPs of the first ring + def all_nodes + ips = @nodes.map { |_, n| n[:ip_ring1] } + return [] if ips.any?(&:empty?) + ips + end + def set_host_password(ip, password) node = @nodes.values.find { |v| v[:ip_ring1] == ip } if node.nil? diff --git a/src/lib/sap_ha/configuration/hana.rb b/src/lib/sap_ha/configuration/hana.rb index 55a5a81..bbb0be1 100644 --- a/src/lib/sap_ha/configuration/hana.rb +++ b/src/lib/sap_ha/configuration/hana.rb @@ -113,7 +113,7 @@ def configured? def validate(verbosity = :verbose) SemanticChecks.instance.check(verbosity) do |check| - check.hana_is_installed(@system_id) + check.hana_is_installed(@system_id, @global_config.cluster.all_nodes) check.ipv4(@virtual_ip, "Virtual IP") check.nonneg_integer(@virtual_ip_mask, "Virtual IP mask") check.integer_in_range(@virtual_ip_mask, 1, 32, "CIDR mask has to be between 1 and 32.", @@ -140,7 +140,7 @@ def validate(verbosity = :verbose) "There is no such HANA user store key detected.", "Secure store key") end if @additional_instance - check.hana_is_installed(@np_system_id) + check.hana_is_installed(@np_system_id,@global_config.cluster.other_nodes) check.sap_instance_number(@np_instance, nil, "Non-Production Instance Number") check.sap_sid(@np_system_id, nil, "Non-Production System ID") check.not_equal(@instance, @np_instance, "SAP HANA instance numbers should not collide", diff --git a/src/lib/sap_ha/semantic_checks.rb b/src/lib/sap_ha/semantic_checks.rb index f54e83b..bc8c4fa 100644 --- a/src/lib/sap_ha/semantic_checks.rb +++ b/src/lib/sap_ha/semantic_checks.rb @@ -22,6 +22,7 @@ require "sap_ha/exceptions" require "yast" require "erb" +require "sap_ha/system/shell_commands" Yast.import "IP" Yast.import "Hostname" @@ -31,6 +32,7 @@ module SapHA class SemanticChecks include Singleton include Yast::Logger + include SapHA::System::ShellCommands attr_accessor :silent attr_reader :checks_passed @@ -50,7 +52,7 @@ def initialize @errors = [] @checks_passed = true @silent = true - @test = !ENV["Y2DIR"].nil? + @no_test = ENV["Y2DIR"].nil? end # Check if the string is a valid IPv4 address @@ -266,15 +268,25 @@ def non_empty_string(value, message, field_name, hide_value = false) end # Check if a HANA db with given sid is installed - def hana_is_installed(value, message = "", field_name = "SID", hide_value = false) - message = "No SAP HANA is installed with given SID." if message.empty? - begin - flag = File.directory?("/usr/sap/" + value.upcase) - rescue StandardError - flag = false + def hana_is_installed(value, nodes) + flag = true + message = '' + my_ips = SapHA::System::Network.ip_addresses + if @no_test + nodes.each do |node| + log.debug("node #{node} #{my_ips}") + if my_ips.include?(node) + status = exec_status("test", "-d", "/usr/sap/#{value.upcase}") + else + status = exec_status("ssh", "-o", "StrictHostKeyChecking=no", node, "test", "-d", "/usr/sap/#{value.upcase}") + end + if status != 0 + flag = false + message += "No SAP HANA #{value} is installed on #{node}\n" + end + end end - flag = true if @test - report_error(flag, message, field_name, value) + report_error(flag, message, 'SID', value) end # Check if string is a block device From ad508638843fb6fe73a8b293e2ee1c533fe1acd3 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Fri, 17 Nov 2023 10:56:26 +0100 Subject: [PATCH 19/30] Enhance changes. --- package/yast2-sap-ha.changes | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package/yast2-sap-ha.changes b/package/yast2-sap-ha.changes index 2bd6e28..294d550 100644 --- a/package/yast2-sap-ha.changes +++ b/package/yast2-sap-ha.changes @@ -5,7 +5,9 @@ Thu Nov 9 08:31:53 UTC 2023 - Peter Varkoly is selected post configuration (bsc#1214603) - yast2-sap-ha does not set global_allocation_limit for non productive database (bsc#1216651) -- Take care that the read values from the saved configuration will not be overridden +- Take care that the read values from the saved configuration will + not be overridden during initialization of the modules +- Check if the required HANA systems are installed on the nodes. - 4.4.6 ------------------------------------------------------------------- From a3f7136a3f8ad6a9e1cb1be94d60579191a6a30b Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Tue, 28 Nov 2023 15:35:32 +0100 Subject: [PATCH 20/30] Fix typo --- src/lib/sap_ha/configuration/hana.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/sap_ha/configuration/hana.rb b/src/lib/sap_ha/configuration/hana.rb index bbb0be1..273cf47 100644 --- a/src/lib/sap_ha/configuration/hana.rb +++ b/src/lib/sap_ha/configuration/hana.rb @@ -214,7 +214,7 @@ def non_production_constraints_validation(check, hash) def apply(role) return false unless configured? - @nlog.info("Appying HANA Configuration") + @nlog.info("Applying HANA Configuration") config_firewall(role) if role == :master if @perform_backup From 4c376a28fa686e048e4309f6212f518cad70d169 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Wed, 29 Nov 2023 08:51:55 +0100 Subject: [PATCH 21/30] Rework the configuration worklflow: 1. Setting up SAP HANA System Replication 2. Setting up SAP HANA HA/DR providers 3. Confiugring the base cluster on all nodes 4. Configuring cluster properties and resources with the new function HANA.finalize The whole class ClusterFinlizer was removed. --- aux/config.yml | 11 ---- aux/config_prd.yml | 11 ---- aux/config_prd_sps03.yml | 11 ---- src/data/sap_ha/scenarios.yaml | 2 +- src/lib/sap_ha/configuration.rb | 3 - src/lib/sap_ha/configuration/cluster.rb | 15 ++--- .../sap_ha/configuration/cluster_finalizer.rb | 59 ------------------- src/lib/sap_ha/configuration/hana.rb | 49 ++++++++++----- src/lib/sap_ha/sap_ha_installation.rb | 2 +- src/lib/sap_ha/system/local.rb | 31 ---------- 10 files changed, 43 insertions(+), 151 deletions(-) delete mode 100644 src/lib/sap_ha/configuration/cluster_finalizer.rb diff --git a/aux/config.yml b/aux/config.yml index d5f115a..2c04aa2 100644 --- a/aux/config.yml +++ b/aux/config.yml @@ -122,17 +122,6 @@ cluster: !ruby/object:SapHA::Configuration::Cluster - :@keys - :@append_hosts - :@host_passwords -cluster_finalizer: !ruby/object:SapHA::Configuration::ClusterFinalizer - global_config: *5 - screen_name: Cluster Configuration Finalizer - exception_type: &6 !ruby/class 'SapHA::Exceptions::BaseConfigException' - yaml_exclude: - - :@nlog - instance_variables: - - :@global_config - - :@screen_name - - :@exception_type - - :@yaml_exclude fencing: !ruby/object:SapHA::Configuration::Fencing global_config: *5 screen_name: Fencing Mechanism diff --git a/aux/config_prd.yml b/aux/config_prd.yml index 5957479..2e15fed 100644 --- a/aux/config_prd.yml +++ b/aux/config_prd.yml @@ -121,17 +121,6 @@ cluster: !ruby/object:SapHA::Configuration::Cluster - :@enable_csync2 - :@keys - :@append_hosts -cluster_finalizer: !ruby/object:SapHA::Configuration::ClusterFinalizer - global_config: *5 - screen_name: Cluster Configuration Finalizer - exception_type: &6 !ruby/class 'SapHA::Exceptions::BaseConfigException' - yaml_exclude: - - :@nlog - instance_variables: - - :@global_config - - :@screen_name - - :@exception_type - - :@yaml_exclude fencing: !ruby/object:SapHA::Configuration::Fencing global_config: *5 screen_name: Fencing Mechanism diff --git a/aux/config_prd_sps03.yml b/aux/config_prd_sps03.yml index eb54705..958588b 100644 --- a/aux/config_prd_sps03.yml +++ b/aux/config_prd_sps03.yml @@ -122,17 +122,6 @@ cluster: !ruby/object:SapHA::Configuration::Cluster - :@enable_csync2 - :@keys - :@append_hosts -cluster_finalizer: !ruby/object:SapHA::Configuration::ClusterFinalizer - global_config: *5 - screen_name: Cluster Configuration Finalizer - exception_type: &6 !ruby/class 'SapHA::Exceptions::BaseConfigException' - yaml_exclude: - - :@nlog - instance_variables: - - :@global_config - - :@screen_name - - :@exception_type - - :@yaml_exclude fencing: !ruby/object:SapHA::Configuration::Fencing global_config: *5 screen_name: Fencing Mechanism diff --git a/src/data/sap_ha/scenarios.yaml b/src/data/sap_ha/scenarios.yaml index 253b802..5c13e69 100644 --- a/src/data/sap_ha/scenarios.yaml +++ b/src/data/sap_ha/scenarios.yaml @@ -12,8 +12,8 @@ - ntp - watchdog - fencing - - cluster - hana + - cluster screen_sequence: &id002 - prerequisites - communication_layer diff --git a/src/lib/sap_ha/configuration.rb b/src/lib/sap_ha/configuration.rb index 6629625..7c3ca97 100644 --- a/src/lib/sap_ha/configuration.rb +++ b/src/lib/sap_ha/configuration.rb @@ -26,7 +26,6 @@ require "sap_ha/helpers" require "sap_ha/node_logger" require "sap_ha/configuration/cluster" -require "sap_ha/configuration/cluster_finalizer" require "sap_ha/configuration/fencing" require "sap_ha/configuration/watchdog" require "sap_ha/configuration/hana" @@ -53,7 +52,6 @@ class HAConfiguration :watchdog, :hana, :ntp, - :cluster_finalizer, :imported, :unattended, :completed, @@ -80,7 +78,6 @@ def initialize(role = :master) @scenario_summary = nil @yaml_configuration = load_scenarios @cluster = Configuration::Cluster.new(self) - @cluster_finalizer = Configuration::ClusterFinalizer.new(self) @fencing = Configuration::Fencing.new(self) @watchdog = Configuration::Watchdog.new(self) @hana = Configuration::HANA.new(self) diff --git a/src/lib/sap_ha/configuration/cluster.rb b/src/lib/sap_ha/configuration/cluster.rb index 306bd28..2fd945b 100644 --- a/src/lib/sap_ha/configuration/cluster.rb +++ b/src/lib/sap_ha/configuration/cluster.rb @@ -287,12 +287,12 @@ def other_nodes_ext def get_primary_on_primary SapHA::System::Network.ip_addresses.each do |my_ip| - @nodes.each do |_, node| - if node[:ip_ring1] == my_ip - return node[:host_name] - end - end - end + @nodes.each do |_, node| + if node[:ip_ring1] == my_ip + return node[:host_name] + end + end + end return nil end @@ -381,10 +381,7 @@ def apply(role) @nlog.log_status(status, "Exported configuration for yast2-cluster", "Could not export configuration for yast2-cluster") flag &= status - #Handle firewall - SapHA::System::Local.config_firewall(@fw_config, role) flag &= SapHA::System::Local.start_cluster_services - flag &= SapHA::System::Local.cluster_maintenance(:on) if role == :master flag &= SapHA::System::Local.add_stonith_resource if role == :master flag end diff --git a/src/lib/sap_ha/configuration/cluster_finalizer.rb b/src/lib/sap_ha/configuration/cluster_finalizer.rb deleted file mode 100644 index d75b348..0000000 --- a/src/lib/sap_ha/configuration/cluster_finalizer.rb +++ /dev/null @@ -1,59 +0,0 @@ -# encoding: utf-8 - -# ------------------------------------------------------------------------------ -# Copyright (c) 2016 SUSE Linux GmbH, Nuernberg, Germany. -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of version 2 of the GNU General Public License as published by the -# Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, contact SUSE Linux GmbH. -# -# ------------------------------------------------------------------------------ -# -# Summary: SUSE High Availability Setup for SAP Products: Cluster members configuration -# Authors: Ilya Manyugin - -require "yast" -require "erb" -require "socket" -require_relative "base_config" -require "sap_ha/system/local" -require "sap_ha/exceptions" - -Yast.import "UI" - -module SapHA - module Configuration - # Cluster members configuration finalizer - class ClusterFinalizer < BaseConfig - def initialize(global_config) - super - log.debug "--- #{self.class}.#{__callee__} ---" - @screen_name = "Cluster Configuration Finalizer" - end - - def configured? - true - end - - def description - "" - end - - def apply(role) - if role == :master - SapHA::System::Local.cluster_maintenance(:off) - @global_config.completed = true - else - true - end - end - end - end -end diff --git a/src/lib/sap_ha/configuration/hana.rb b/src/lib/sap_ha/configuration/hana.rb index 273cf47..6af0dd2 100644 --- a/src/lib/sap_ha/configuration/hana.rb +++ b/src/lib/sap_ha/configuration/hana.rb @@ -215,7 +215,7 @@ def non_production_constraints_validation(check, hash) def apply(role) return false unless configured? @nlog.info("Applying HANA Configuration") - config_firewall(role) + configure_firewall(role) if role == :master if @perform_backup SapHA::System::Hana.make_backup(@system_id, @backup_user, @backup_file, @instance) @@ -224,7 +224,6 @@ def apply(role) secondary_password = @global_config.cluster.host_passwords[secondary_host_name] SapHA::System::Hana.copy_ssfs_keys(@system_id, secondary_host_name, secondary_password) SapHA::System::Hana.enable_primary(@system_id, @site_name_1) - configure_crm else # secondary node SapHA::System::Hana.hdb_stop(@system_id) primary_host_name = @global_config.cluster.other_nodes_ext.first[:hostname] @@ -238,20 +237,14 @@ def apply(role) true end - def cleanup_hana_resources - # @FIXME: Workaround for Azure-specific issue that needs investigation - # https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/sap-hana-high-availability - if @global_config.platform == "azure" - rsc = "rsc_SAPHana_#{@system_id}_HDB#{@instance}" - cleanup_status = exec_status("crm", "resource", "cleanup", rsc) - @nlog.log_status(cleanup_status.exitstatus == 0, - "Performed resource cleanup for #{rsc}", - "Could not clean up #{rsc}") - end + def finalize + configure_crm + activating_msr end + private + def configure_crm - # TODO: move this to SapHA::System::Local.configure_crm primary_host_name = @global_config.cluster.get_primary_on_primary secondary_host_name = @global_config.cluster.other_nodes_ext.first[:hostname] crm_conf = Helpers.render_template("tmpl_cluster_config.erb", binding) @@ -262,10 +255,36 @@ def configure_crm "Could not configure HANA cluster resources", out) end - def config_firewall(role) + def activating_msr + msr = "msl_SAPHana_#{@system_id}_HDB#{@instance}" + out, status = exec_outerr_status("crm", "resource", "refresh", msr) + out, status = exec_outerr_status("crm", "resource", "maintenance", msr, "off") + end + + def cleanup_hana_resources + # @FIXME: Workaround for Azure-specific issue that needs investigation + # https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/sap-hana-high-availability + if @global_config.platform == "azure" + rsc = "rsc_SAPHana_#{@system_id}_HDB#{@instance}" + cleanup_status = exec_status("crm", "resource", "cleanup", rsc) + @nlog.log_status(cleanup_status.exitstatus == 0, + "Performed resource cleanup for #{rsc}", + "Could not clean up #{rsc}") + end + end + + # Adapt the firewall depending on the @global_config.cluster.fw_config + # Even if the firewall is already configured the TCP port 8080 will be opened for internal RPC communication during setup + # If the firewall should be stoped during cofiguration no other action is necessary + # If the firewall should be configured in the first step the HANA-Services will be generated by hana-firewall. + # After them the generated services and the service cluster will be added to the default zone. + def configure_firewall(role) case @global_config.cluster.fw_config when "done" @nlog.info("Firewall is already configured") + if role != :master + _s = exec_status("/usr/bin/firewall-cmd", "--add-port", "8080/tcp") + end when "off" @nlog.info("Firewall will be turned off") SapHA::System::Local.systemd_unit(:stop, :service, "firewalld") @@ -280,6 +299,8 @@ def config_firewall(role) if role != :master _s = exec_status("/usr/bin/firewall-cmd", "--add-port", "8080/tcp") end + _s = exec_status("/usr/bin/firewall-cmd", "--add-service", "cluster") + _s = exec_status("/usr/bin/firewall-cmd", "--permanent", "--add-service", "cluster") HANA_FW_SERVICES.each do |service| _s = exec_status("/usr/bin/firewall-cmd", "--add-service", service) _s = exec_status("/usr/bin/firewall-cmd", "--permanent", "--add-service", service) diff --git a/src/lib/sap_ha/sap_ha_installation.rb b/src/lib/sap_ha/sap_ha_installation.rb index 76f5587..14d6600 100644 --- a/src/lib/sap_ha/sap_ha_installation.rb +++ b/src/lib/sap_ha/sap_ha_installation.rb @@ -57,7 +57,7 @@ def run next_node log.info "--- #{self.class}.#{__callee__}: finished configuring node #{node[:hostname]} ---" end - @config.cluster_finalizer.apply(:master) + @config.cluster.finalize @ui.unblock if @ui NodeLogger.summary :next diff --git a/src/lib/sap_ha/system/local.rb b/src/lib/sap_ha/system/local.rb index 518ea43..cae7e58 100644 --- a/src/lib/sap_ha/system/local.rb +++ b/src/lib/sap_ha/system/local.rb @@ -189,37 +189,6 @@ def join_cluster(_ip_address) raise "Not implemented" end - def config_firewall(fw_config, role) - case fw_config - when "done" - NodeLogger.info("Firewall is already configured") - when "off" - NodeLogger.info("Firewall will be turned off") - systemd_unit(:stop, :service, "firewalld") - when "setup" - NodeLogger.info("Firewall will be configured for cluster services.") - out, status = exec_outerr_status("/usr/bin/firewall-cmd", "--state") - return if status.exitstatus != 0 - out, status = exec_outerr_status("/usr/bin/firewall-cmd", "--add-service", "cluster") - NodeLogger.log_status( - status.exitstatus == 0, - "Open cluster service in firewall", - "Could not open cluster service in firewall", - out - ) - out, status = exec_outerr_status("/usr/bin/firewall-cmd", "--permanent", "--add-service", "cluster") - NodeLogger.log_status( - status.exitstatus == 0, - "Open cluster service permanent in firewall", - "Could not open cluster service permanent in firewall", - out - ) - if role != :master - exec_status("/usr/bin/firewall-cmd", "--add-port", "8080/tcp") - end - end - end - def change_password(user_name, password) cmd_string = "#{user_name}:#{password}" out, status = exec_outerr_status_stdin("chpasswd", cmd_string) From 346e00502234fac34d6d07279784cba2abc07485 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Wed, 29 Nov 2023 08:55:52 +0100 Subject: [PATCH 22/30] New version --- package/yast2-sap-ha.changes | 12 ++++++++++++ package/yast2-sap-ha.spec | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/package/yast2-sap-ha.changes b/package/yast2-sap-ha.changes index 294d550..008e977 100644 --- a/package/yast2-sap-ha.changes +++ b/package/yast2-sap-ha.changes @@ -1,3 +1,15 @@ +------------------------------------------------------------------- +Wed Nov 29 07:52:36 UTC 2023 - Peter Varkoly + +- yast2-sap-ha setup workflow is bad (bsc#1217596) + Reworking the workflow: + 1. Setting up SAP HANA System Replication + 2. Setting up SAP HANA HA/DR providers + 3. Confiugring the base cluster on all nodes + 4. Configuring cluster properties and resources with the new function HANA.finalize + The whole class ClusterFinlizer was removed. +- 4.4.7 + ------------------------------------------------------------------- Thu Nov 9 08:31:53 UTC 2023 - Peter Varkoly diff --git a/package/yast2-sap-ha.spec b/package/yast2-sap-ha.spec index ed09a35..fe4ff2e 100644 --- a/package/yast2-sap-ha.spec +++ b/package/yast2-sap-ha.spec @@ -17,7 +17,7 @@ Name: yast2-sap-ha -Version: 4.4.6 +Version: 4.4.7 Release: 0 BuildArch: noarch Source0: %{name}-%{version}.tar.bz2 From 97cb9aba87ca0fcef999ba2b964886e6772da38b Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Wed, 29 Nov 2023 10:45:18 +0100 Subject: [PATCH 23/30] Use the right class --- src/lib/sap_ha/sap_ha_installation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/sap_ha/sap_ha_installation.rb b/src/lib/sap_ha/sap_ha_installation.rb index 14d6600..5f36250 100644 --- a/src/lib/sap_ha/sap_ha_installation.rb +++ b/src/lib/sap_ha/sap_ha_installation.rb @@ -57,7 +57,7 @@ def run next_node log.info "--- #{self.class}.#{__callee__}: finished configuring node #{node[:hostname]} ---" end - @config.cluster.finalize + @config.hana.finalize @ui.unblock if @ui NodeLogger.summary :next From 8880546965b0476ed2391ef3dae9d70d5b8b613a Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Wed, 29 Nov 2023 18:41:10 +0100 Subject: [PATCH 24/30] Use or ignore output --- src/lib/sap_ha/configuration/hana.rb | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/lib/sap_ha/configuration/hana.rb b/src/lib/sap_ha/configuration/hana.rb index 6af0dd2..97beab0 100644 --- a/src/lib/sap_ha/configuration/hana.rb +++ b/src/lib/sap_ha/configuration/hana.rb @@ -258,7 +258,13 @@ def configure_crm def activating_msr msr = "msl_SAPHana_#{@system_id}_HDB#{@instance}" out, status = exec_outerr_status("crm", "resource", "refresh", msr) + @nlog.log_status(status.exitstatus == 0, + "#{msr} status refresh OK", + "Could not refresh status of #{msr}: #{out}") out, status = exec_outerr_status("crm", "resource", "maintenance", msr, "off") + @nlog.log_status(status.exitstatus == 0, + "#{msr} maintenance turned off.", + "Could turn of maintenance of #{msr}: #{out}") end def cleanup_hana_resources @@ -326,14 +332,14 @@ def adjust_global_ini(role) add_plugin_to_global_ini("SUS_COSTOPT", @system_id) if role != :master add_plugin_to_global_ini("NON_PROD", @np_system_id) if role != :master command = ["hdbnsutil", "-reloadHADRProviders"] - out, status = su_exec_outerr_status("#{@np_system_id.downcase}adm", *command) + _out, _status = su_exec_outerr_status("#{@np_system_id.downcase}adm", *command) else # performance optimized add_plugin_to_global_ini("SUS_CHKSRV", @system_id) add_plugin_to_global_ini("SUS_TKOVER", @system_id) end command = ["hdbnsutil", "-reloadHADRProviders"] - out, status = su_exec_outerr_status("#{@system_id.downcase}adm", *command) + _out, _status = su_exec_outerr_status("#{@system_id.downcase}adm", *command) end # Activates the plugin in global ini @@ -342,8 +348,8 @@ def add_plugin_to_global_ini(plugin, sid) if File.exist?("#{sr_path}.erb") sr_path = Helpers.write_var_file(plugin, Helpers.render_template("GLOBAL_INI_#{plugin}.erb", binding)) end - command = ["/usr/sbin/SAPHanaSR-manageProvider", "--add", "--sid", sid, sr_path] - out, status = su_exec_outerr_status("#{sid.downcase}adm", *command) + command = ["/usr/sbin/SAPHanaSR-manageProvider", "--add", "--reconfigure", "--sid", sid, sr_path] + _out, _status = su_exec_outerr_status("#{sid.downcase}adm", *command) end end end From 4707761dd125c7667fb2db4d6eb5496bbdca35e5 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Fri, 1 Dec 2023 10:28:28 +0100 Subject: [PATCH 25/30] New function to wait until primary get idle. Replace tabs with spaces. --- src/lib/sap_ha/configuration/hana.rb | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/lib/sap_ha/configuration/hana.rb b/src/lib/sap_ha/configuration/hana.rb index 97beab0..10e1d05 100644 --- a/src/lib/sap_ha/configuration/hana.rb +++ b/src/lib/sap_ha/configuration/hana.rb @@ -95,7 +95,7 @@ def initialize(global_config) def additional_instance=(value) @additional_instance = value return unless value - @prefer_takeover = false + @prefer_takeover = false @production_constraints = { global_alloc_limit_prod: "0", global_alloc_limit_non: "0", @@ -239,7 +239,8 @@ def apply(role) def finalize configure_crm - activating_msr + wait_idle + activating_msr end private @@ -255,6 +256,15 @@ def configure_crm "Could not configure HANA cluster resources", out) end + def wait_idle + primary_host_name = @global_config.cluster.other_nodes_ext.first[:hostname] + while true + out, status = exec_outerr_status("crmadmin","--quiet","--status",primary_host_name) + break if out == "S_IDLE" + log.info("wait_idle status of #{primary_host_name} is #{out}") + sleep 5 + end + end def activating_msr msr = "msl_SAPHana_#{@system_id}_HDB#{@instance}" out, status = exec_outerr_status("crm", "resource", "refresh", msr) @@ -264,7 +274,7 @@ def activating_msr out, status = exec_outerr_status("crm", "resource", "maintenance", msr, "off") @nlog.log_status(status.exitstatus == 0, "#{msr} maintenance turned off.", - "Could turn of maintenance of #{msr}: #{out}") + "Could turn off maintenance on #{msr}: #{out}") end def cleanup_hana_resources @@ -318,9 +328,9 @@ def configure_firewall(role) # Creates the sudoers file def adapt_sudoers - if File.exist?(SapHA::Helpers.data_file_path("SUDOERS_HANASR.erb")) - Helpers.write_file("/etc/sudoers.d/saphanasr.conf",Helpers.render_template("SUDOERS_HANASR.erb", binding)) - end + if File.exist?(SapHA::Helpers.data_file_path("SUDOERS_HANASR.erb")) + Helpers.write_file("/etc/sudoers.d/saphanasr.conf",Helpers.render_template("SUDOERS_HANASR.erb", binding)) + end end # Activates all necessary plugins based on role an scenario From cb318e1b721cf8f575a1c58c0e3a64045d423bd7 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Fri, 1 Dec 2023 12:08:48 +0100 Subject: [PATCH 26/30] Set ms in maintenance mode --- src/data/sap_ha/tmpl_cluster_config.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/sap_ha/tmpl_cluster_config.erb b/src/data/sap_ha/tmpl_cluster_config.erb index b3ac6d3..cd380d6 100644 --- a/src/data/sap_ha/tmpl_cluster_config.erb +++ b/src/data/sap_ha/tmpl_cluster_config.erb @@ -40,7 +40,7 @@ primitive rsc_SAPHana_<%= @system_id -%>_HDB<%= @instance -%> ocf:suse:SAPHana \ meta priority="100" ms msl_SAPHana_<%= @system_id -%>_HDB<%= @instance -%> rsc_SAPHana_<%= @system_id -%>_HDB<%= @instance -%> \ - meta clone-max="2" clone-node-max="1" interleave="true" + meta clone-max="2" clone-node-max="1" interleave="true" maintenance="true" primitive rsc_ip_<%= @system_id -%>_HDB<%= @instance -%> ocf:heartbeat:IPaddr2 \ op monitor interval="10" timeout="20" \ From 0f1dcc4564b6dd169d6b63a658ba47d3e3822635 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Fri, 1 Dec 2023 12:09:18 +0100 Subject: [PATCH 27/30] Use the right node. Do not wait infinitively --- src/lib/sap_ha/configuration/hana.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/lib/sap_ha/configuration/hana.rb b/src/lib/sap_ha/configuration/hana.rb index 10e1d05..0a95cd3 100644 --- a/src/lib/sap_ha/configuration/hana.rb +++ b/src/lib/sap_ha/configuration/hana.rb @@ -257,12 +257,15 @@ def configure_crm end def wait_idle - primary_host_name = @global_config.cluster.other_nodes_ext.first[:hostname] + primary_host_name = @global_config.cluster.get_primary_on_primary + counter = 0 while true out, status = exec_outerr_status("crmadmin","--quiet","--status",primary_host_name) break if out == "S_IDLE" log.info("wait_idle status of #{primary_host_name} is #{out}") - sleep 5 + counter++ + break if counter > 10 + sleep 6 end end def activating_msr From c272e1c4fbb48fccadd827bcfc0d9176c8d37c18 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Sat, 2 Dec 2023 11:08:36 +0100 Subject: [PATCH 28/30] Increment --- src/lib/sap_ha/configuration/hana.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/sap_ha/configuration/hana.rb b/src/lib/sap_ha/configuration/hana.rb index 0a95cd3..0623ea6 100644 --- a/src/lib/sap_ha/configuration/hana.rb +++ b/src/lib/sap_ha/configuration/hana.rb @@ -263,7 +263,7 @@ def wait_idle out, status = exec_outerr_status("crmadmin","--quiet","--status",primary_host_name) break if out == "S_IDLE" log.info("wait_idle status of #{primary_host_name} is #{out}") - counter++ + counter += 1 break if counter > 10 sleep 6 end From 0acb21280264b9f02c5e560e53cc3974e8060303 Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Thu, 7 Dec 2023 09:52:10 +0100 Subject: [PATCH 29/30] Now wait_idle can handle all nodes. --- src/lib/sap_ha/configuration/hana.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/lib/sap_ha/configuration/hana.rb b/src/lib/sap_ha/configuration/hana.rb index 0623ea6..75a4a05 100644 --- a/src/lib/sap_ha/configuration/hana.rb +++ b/src/lib/sap_ha/configuration/hana.rb @@ -239,7 +239,7 @@ def apply(role) def finalize configure_crm - wait_idle + wait_idle(@global_config.cluster.get_primary_on_primary) activating_msr end @@ -256,18 +256,19 @@ def configure_crm "Could not configure HANA cluster resources", out) end - def wait_idle - primary_host_name = @global_config.cluster.get_primary_on_primary + # Wait until the node is in state S_IDLE but maximal 60 seconds + def wait_idle(node) counter = 0 while true - out, status = exec_outerr_status("crmadmin","--quiet","--status",primary_host_name) + out, status = exec_outerr_status("crmadmin","--quiet","--status",node) break if out == "S_IDLE" - log.info("wait_idle status of #{primary_host_name} is #{out}") + log.info("wait_idle status of #{node} is #{out}") counter += 1 break if counter > 10 sleep 6 end end + def activating_msr msr = "msl_SAPHana_#{@system_id}_HDB#{@instance}" out, status = exec_outerr_status("crm", "resource", "refresh", msr) From bd5cbfcf4b24b81d0cfc39d68a910b47cdb1e12f Mon Sep 17 00:00:00 2001 From: Peter Varkoly Date: Thu, 7 Dec 2023 11:43:12 +0100 Subject: [PATCH 30/30] New helper script to test if hana is running on a node --- aux/is_hana_running.sh | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 aux/is_hana_running.sh diff --git a/aux/is_hana_running.sh b/aux/is_hana_running.sh new file mode 100644 index 0000000..75f7b4d --- /dev/null +++ b/aux/is_hana_running.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# + +while true +do + if [ "$( /usr/sap/hostctrl/exe/sapcontrol -nr 00 -function GetProcessList | grep hdbindexserver )" ]; then + echo -n "RUN " >> /var/log/hana-state + date >> /var/log/hana-state + else + echo -n "NOT " >> /var/log/hana-state + date >> /var/log/hana-state + fi + sleep 1 +done +