Hello community,

here is the log from the commit of package yast2-cluster for openSUSE:Factory 
checked in at 2019-10-16 09:18:52
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/yast2-cluster (Old)
 and      /work/SRC/openSUSE:Factory/.yast2-cluster.new.2352 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "yast2-cluster"

Wed Oct 16 09:18:52 2019 rev:36 rq:738720 version:4.2.5

Changes:
--------
--- /work/SRC/openSUSE:Factory/yast2-cluster/yast2-cluster.changes      
2019-09-30 15:58:18.721390182 +0200
+++ /work/SRC/openSUSE:Factory/.yast2-cluster.new.2352/yast2-cluster.changes    
2019-10-16 09:18:53.614909602 +0200
@@ -1,0 +2,17 @@
+Fri Oct 11 07:48:01 UTC 2019 - Yuan Ren <[email protected]>
+
+- bsc#1149089 corosync-qdevice service ready to be configured
+        * Add corosync-qdevice RPM package into Yast2-cluster
+        * Add `IP Version` option in Dialog
+        * Member Address is enabled whatever transport and ip version
+        * Member Address is required/optional relations based on different 
transport or IP version used
+        * Auto Generate Node ID would disabled once IPV6 selected
+        * Auto Generate Node ID is required if UDP&IPv4&Member Address is empty
+        * When enable corosync-qdevice but Member Address is empty, a warning 
would occur
+        * Corosync-qdevice algorithm can only choose ffsplit
+        * Qdevice votes disabled to be set mannually, defualt is "1"
+        * expected_votes should be enabled only in nodelist empty&ipv4&udp
+        * Add corosync-qdevice service start/stop/status and enabale/disable 
at booting time
+- Version 4.2.5
+
+-------------------------------------------------------------------

Old:
----
  yast2-cluster-4.2.4.tar.bz2

New:
----
  yast2-cluster-4.2.5.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ yast2-cluster.spec ++++++
--- /var/tmp/diff_new_pack.Vzdw5u/_old  2019-10-16 09:18:55.326905190 +0200
+++ /var/tmp/diff_new_pack.Vzdw5u/_new  2019-10-16 09:18:55.358905108 +0200
@@ -19,7 +19,7 @@
 %define _fwdefdir %{_libexecdir}/firewalld/services
 
 Name:           yast2-cluster
-Version:        4.2.4
+Version:        4.2.5
 Release:        0
 Summary:        Configuration of cluster
 License:        GPL-2.0-only
@@ -34,7 +34,6 @@
 BuildRequires:  yast2-devtools >= 4.2.2
 BuildRequires:  rubygem(%{rb_default_ruby_abi}:yast-rake)
 
-Requires:       yast2 >= 4.0.39
 Requires:       yast2 >= 4.1.3
 Requires:       yast2-ruby-bindings >= 1.0.0
 

++++++ yast2-cluster-4.2.4.tar.bz2 -> yast2-cluster-4.2.5.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-cluster-4.2.4/package/yast2-cluster.changes 
new/yast2-cluster-4.2.5/package/yast2-cluster.changes
--- old/yast2-cluster-4.2.4/package/yast2-cluster.changes       2019-09-27 
14:29:06.000000000 +0200
+++ new/yast2-cluster-4.2.5/package/yast2-cluster.changes       2019-10-16 
05:12:19.000000000 +0200
@@ -1,4 +1,21 @@
 -------------------------------------------------------------------
+Fri Oct 11 07:48:01 UTC 2019 - Yuan Ren <[email protected]>
+
+- bsc#1149089 corosync-qdevice service ready to be configured
+        * Add corosync-qdevice RPM package into Yast2-cluster
+        * Add `IP Version` option in Dialog
+        * Member Address is enabled whatever transport and ip version
+        * Member Address is required/optional relations based on different 
transport or IP version used
+        * Auto Generate Node ID would disabled once IPV6 selected
+        * Auto Generate Node ID is required if UDP&IPv4&Member Address is empty
+        * When enable corosync-qdevice but Member Address is empty, a warning 
would occur
+        * Corosync-qdevice algorithm can only choose ffsplit
+        * Qdevice votes disabled to be set mannually, defualt is "1"
+        * expected_votes should be enabled only in nodelist empty&ipv4&udp
+        * Add corosync-qdevice service start/stop/status and enabale/disable 
at booting time
+- Version 4.2.5
+
+-------------------------------------------------------------------
 Wed Sep 25 07:06:51 UTC 2019 - nick wang <[email protected]>
 
 - bsc#1151687, update the open ports to support pacemaker-remote,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-cluster-4.2.4/package/yast2-cluster.spec 
new/yast2-cluster-4.2.5/package/yast2-cluster.spec
--- old/yast2-cluster-4.2.4/package/yast2-cluster.spec  2019-09-27 
14:29:06.000000000 +0200
+++ new/yast2-cluster-4.2.5/package/yast2-cluster.spec  2019-10-16 
05:12:19.000000000 +0200
@@ -18,7 +18,7 @@
 %define _fwdefdir %{_libexecdir}/firewalld/services
 
 Name:           yast2-cluster
-Version:        4.2.4
+Version:        4.2.5
 Release:        0
 Summary:        Configuration of cluster
 License:        GPL-2.0-only
@@ -33,7 +33,6 @@
 BuildRequires:  update-desktop-files
 BuildRequires:  yast2-devtools >= 4.2.2
 
-Requires:       yast2 >= 4.0.39
 Requires:       yast2-ruby-bindings >= 1.0.0
 Requires:       yast2 >= 4.1.3
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-cluster-4.2.4/src/include/cluster/dialogs.rb 
new/yast2-cluster-4.2.5/src/include/cluster/dialogs.rb
--- old/yast2-cluster-4.2.4/src/include/cluster/dialogs.rb      2019-09-27 
14:29:06.000000000 +0200
+++ new/yast2-cluster-4.2.5/src/include/cluster/dialogs.rb      2019-10-16 
05:12:19.000000000 +0200
@@ -70,6 +70,12 @@
       @usable_interface = []
     end
 
+    # IP check between address and IP Version
+    def ip_matching_check(ip_address, ip_version)
+      return (ip_version.to_s == "ipv4" && IP.Check4(ip_address.to_s)) ||
+        (ip_version.to_s == "ipv6" && IP.Check6(ip_address.to_s))
+    end
+
     # return `cancel or a string
     def text_input_dialog(title, value)
       ret = nil
@@ -152,7 +158,9 @@
 
     def ValidNodeID
       if Cluster.memberaddr.size <= 0
-         return true
+        UI.SetFocus(:nodeid)
+        Popup.Message(_("Auto Generate Node ID has to be selected"))
+        return false
       end
 
       i = 0
@@ -161,7 +169,7 @@
 
       Builtins.foreach(Cluster.memberaddr) do |value|
         if value[:nodeid].to_i <= 0
-          Popup.Message(_("Node ID has to be fulfilled with a positive 
integer"))
+          Popup.Message(_("Node ID has to be fulfilled with a positive integer 
or select Auto Generate Node ID"))
           UI.ChangeWidget(:memberaddr, :CurrentItem, i)
           i = 0
           raise Break
@@ -188,6 +196,7 @@
     # BNC#871970, change member address struct
     def ValidateCommunication
       i = 0
+      ip_version = UI.QueryWidget(Id(:ip_version), :Value)
 
       if UI.QueryWidget(Id(:cluster_name), :Value) == ""
         Popup.Message(_("The cluster name has to be fulfilled"))
@@ -195,42 +204,33 @@
         return false
       end
 
-      if UI.QueryWidget(Id(:transport), :Value) == "udpu"
-        i = 0
-        Builtins.foreach(Cluster.memberaddr) do |value|
-          if  !IP.Check(value[:addr1]) || ( UI.QueryWidget(Id(:enable2), 
:Value) && !IP.Check(value[:addr2]) )
-            UI.ChangeWidget(:memberaddr, :CurrentItem, i)
-            i = 0
-            raise Break
-          end
-          i = Ops.add(i, 1)
-        end
-        if i == 0
-          UI.SetFocus(:memberaddr)
-          Popup.Message(_("The Member Address has to be fulfilled"))
-          return false
-        end
-      else
-        #BNC#880242, expected_votes must have value when "udp"
-        if UI.QueryWidget(Id(:expected_votes), :Value) == ""
-          Popup.Message(_("The Expected Votes has to be fulfilled when 
multicast transport is configured"))
-          UI.SetFocus(:expected_votes)
-          return false
-        end
+      if UI.QueryWidget(Id(:transport), :Value) == "udp"
 
-        if IP.Check(Convert.to_string(UI.QueryWidget(Id(:bindnetaddr1), 
:Value))) == false
-          Popup.Message(_("The Bind Network Address has to be fulfilled"))
+        if !ip_matching_check(UI.QueryWidget(Id(:bindnetaddr1), :Value), 
ip_version)
+          Popup.Message(_("IP Version doesn't match with Bind Network Address 
in Channel"))
           UI.SetFocus(:bindnetaddr1)
           return false
         end
 
-        if !IP.Check(Convert.to_string(UI.QueryWidget(Id(:mcastaddr1), 
:Value)))
-          Popup.Message(_("The Multicast Address has to be fulfilled"))
+        if !ip_matching_check(UI.QueryWidget(Id(:mcastaddr1), :Value), 
ip_version)
+          Popup.Message(_("IP Version doesn't match with Multicast Address in 
Channel"))
           UI.SetFocus(:mcastaddr1)
           return false
         end
       end
 
+      if Cluster.memberaddr.size <= 0
+        if UI.QueryWidget(Id(:transport), :Value) == "udpu" || ip_version.to_s 
== "ipv6"
+          Popup.Message(_("Member address is required"))
+          return false
+          #BNC#880242, expected_votes must have value when "udp" without 
nodelist
+        elsif UI.QueryWidget(Id(:expected_votes), :Value) == ""
+          Popup.Message(_("The Expected Votes has to be fulfilled when 
multicast transport is configured without nodelist"))
+          UI.SetFocus(:expected_votes)
+          return false
+        end
+      end
+
       if !Builtins.regexpmatch(
           Convert.to_string(UI.QueryWidget(Id(:mcastport1), :Value)),
           "^[0-9]+$"
@@ -242,18 +242,14 @@
 
       if UI.QueryWidget(Id(:enable2), :Value)
         if UI.QueryWidget(Id(:transport), :Value) == "udp"
-          if IP.Check(
-              Convert.to_string(UI.QueryWidget(Id(:bindnetaddr2), :Value))
-            ) == false
-            Popup.Message(_("The Bind Network Address has to be fulfilled"))
+          if !ip_matching_check(UI.QueryWidget(Id(:bindnetaddr2), :Value), 
ip_version)
+            Popup.Message(_("IP Version doesn't match with Bind Network 
Address in Redundant Channel"))
             UI.SetFocus(:bindnetaddr2)
             return false
           end
 
-          if IP.Check(
-              Convert.to_string(UI.QueryWidget(Id(:mcastaddr2), :Value))
-            ) == false
-            Popup.Message(_("The Multicast Address has to be fulfilled"))
+          if !ip_matching_check(UI.QueryWidget(Id(:mcastaddr2), :Value), 
ip_version)
+            Popup.Message(_("IP Version doesn't match with Multicast Address 
in Redundant Channel"))
             UI.SetFocus(:mcastaddr2)
             return false
           end
@@ -278,14 +274,29 @@
         end
       end
 
-      if !UI.QueryWidget(Id(:autoid), :Value ) && ( 
UI.QueryWidget(Id(:transport), :Value) == "udpu" )
+      Builtins.foreach(Cluster.memberaddr) do |value|
+        if !ip_matching_check(value[:addr1], ip_version) ||
+            (UI.QueryWidget(Id(:enable2), :Value) && 
!ip_matching_check(value[:addr2], ip_version))
+          UI.ChangeWidget(:memberaddr, :CurrentItem, i)
+          if Cluster.memberaddr.size <= 0 && (UI.QueryWidget(Id(:transport), 
:Value) == "udp" && ip_version.to_s == "ipv4")
+            raise Break
+          else
+            UI.SetFocus(:memberaddr)
+            Popup.Message(_("IP Version doesn't match with addresses within 
Member Address"))
+            i = 0
+            return false
+          end
+        end
+        i += 1
+      end
+
+      if !UI.QueryWidget(Id(:autoid), :Value )
         ret = ValidNodeID()
         if !ret
            UI.SetFocus(Id(:memberaddr))
            return false
         end
       end
-
       true
     end
 
@@ -361,6 +372,7 @@
       Cluster.transport = Convert.to_string(
         UI.QueryWidget(Id(:transport), :Value)
       )
+      Cluster.ip_version = UI.QueryWidget(Id(:ip_version), :Value).to_s
 
       #BNC#871970, clear second IP when redundant channel is disabled
       if !UI.QueryWidget(Id(:enable2), :Value)
@@ -384,6 +396,17 @@
       )
     end
 
+    def expectedvotes_switch
+      if Cluster.memberaddr.size <= 0 &&
+          UI.QueryWidget(Id(:ip_version), :Value).to_s == "ipv4" &&
+          UI.QueryWidget(Id(:transport), :Value) == "udp"
+        UI.ChangeWidget(Id(:expected_votes), :Enabled, true)
+      else
+        UI.ChangeWidget(Id(:expected_votes), :Value, "")
+        UI.ChangeWidget(Id(:expected_votes), :Enabled, false)
+      end
+    end
+
 
     # BNC#871970, change member address struct to memberaddr
     def transport_switch
@@ -394,16 +417,20 @@
       enable2 = udp && enable2
 
       UI.ChangeWidget(Id(:mcastaddr1), :Enabled, enable1)
-      UI.ChangeWidget(Id(:memberaddr), :Enabled, !enable1)
-      UI.ChangeWidget(Id(:memberaddr_add), :Enabled, !enable1)
-      UI.ChangeWidget(Id(:memberaddr_del), :Enabled, !enable1)
-      UI.ChangeWidget(Id(:memberaddr_edit), :Enabled, !enable1)
 
       UI.ChangeWidget(Id(:mcastaddr2), :Enabled, enable2)
 
       UI.ChangeWidget(Id(:bindnetaddr1), :Enabled, enable1)
       UI.ChangeWidget(Id(:bindnetaddr2), :Enabled, enable2)
 
+      ip = UI.QueryWidget(Id(:ip_version), :Value).to_s
+      if ip == "ipv6"
+        UI.ChangeWidget(Id(:autoid), :Value, false)
+        UI.ChangeWidget(Id(:autoid), :Enabled, false)
+      else
+        UI.ChangeWidget(Id(:autoid), :Enabled, true)
+      end
+
       nil
     end
 
@@ -440,14 +467,27 @@
         end
       end
 
-      transport = ComboBox(
-        Id(:transport),
-        Opt(:hstretch, :notify),
-        _("Transport:"),
-        [
-        Item(Id("udp"),"Multicast"),
-        Item(Id("udpu"),"Unicast")
-        ]
+      hid = VBox(
+        HBox(
+          ComboBox(
+            Id(:transport),
+            Opt(:hstretch, :notify),
+            _("Transport:"),
+            [
+            Item(Id("udp"), "Multicast"),
+            Item(Id("udpu"), "Unicast")
+            ]
+          ),
+          ComboBox(
+            Id(:ip_version),
+            Opt(:hstretch, :notify),
+            _("IP Version:"),
+            [
+              Item(Id("ipv4"), "IPv4"),
+              Item(Id("ipv6"), "IPv6")
+            ]
+          )
+        )
       )
 
       iface = Frame(
@@ -511,7 +551,7 @@
         ))
 
       contents = VBox(
-        transport,
+        HBox(hid),
         HBox(HWeight(1, VBox(iface)), HWeight(1, VBox(riface))),
         ip_table,
         HBox(nid),
@@ -530,9 +570,10 @@
       UI.ChangeWidget(Id(:autoid), :Value, Cluster.autoid)
       UI.ChangeWidget(Id(:cluster_name), :Value, Cluster.cluster_name)
       UI.ChangeWidget(Id(:expected_votes), :Value, Cluster.expected_votes)
-      UI.ChangeWidget(:expected_votes, :ValidChars, "0123456789");
+      UI.ChangeWidget(:expected_votes, :ValidChars, "0123456789")
 
       UI.ChangeWidget(Id(:transport), :Value, Cluster.transport)
+      UI.ChangeWidget(Id(:ip_version), :Value, Cluster.ip_version)
 
       UI.ChangeWidget(Id(:rrpmode), :Value, Cluster.rrpmode)
       if "none" == Cluster.rrpmode
@@ -587,25 +628,10 @@
       while true
         fill_memberaddr_entries
         transport_switch
+        expectedvotes_switch
 
         ret = UI.UserInput
 
-        if ret == :bindnetaddr1 || ret == :bindnetaddr2 || ret == :mcastaddr1 
||
-            ret == :mcastaddr2
-          ip6 = false
-          netaddr = Convert.to_string(UI.QueryWidget(Id(ret), :Value))
-          ip6 = IP.Check6(netaddr)
-          if ip6
-            Cluster.ip_version = "ipv6"
-            UI.ChangeWidget(Id(:autoid), :Value, false)
-            UI.ChangeWidget(Id(:autoid), :Enabled, false)
-          else
-            Cluster.ip_version = "ipv4"
-            UI.ChangeWidget(Id(:autoid), :Enabled, true)
-          end
-          next
-        end
-
         if ret == :enable2
           if UI.QueryWidget(Id(:enable2), :Value)
             # Changewidget items will change value to first one automatically
@@ -720,12 +746,6 @@
         return false
       end
 
-      if UI.QueryWidget(Id(:qdevice_votes), :Value).to_i <= 0
-        Popup.Message(_("Qdevice votes must be a positive integer"))
-        UI.SetFocus(:qdevice_votes)
-        return false
-      end
-
       if !IP.Check(UI.QueryWidget(Id(:qdevice_host), :Value))
         Popup.Message(_("Qdevice host mush have a valid IP address"))
         UI.SetFocus(:qdevice_host)
@@ -738,13 +758,6 @@
         return false
       end
 
-      if !["ffsplit", "lms", "test", 
"2nodelms"].include?(UI.QueryWidget(Id(:qdevice_algorithm), :Value))
-        Popup.Message(_("The algorithm only can be one of the ffsplit, lms, 
test or 2nodelms." \
-          "YaST will overwrite test and 2nodelms."))
-        UI.SetFocus(Id(:algorithm))
-        return false
-      end
-
       if !["lowest", 
"highest"].include?(UI.QueryWidget(Id(:qdevice_tie_breaker), :Value)) &&
         (UI.QueryWidget(Id(:qdevice_tie_breaker), :Value).to_i <= 0)
         Popup.Message(_("The tie breaker can be one of lowest, highest or a 
valid node id (number)"))
@@ -752,6 +765,10 @@
         return false
       end
 
+      if UI.QueryWidget(Id(:corosync_qdevice), :Value) && 
Cluster.memberaddr.size <= 0
+        Popup.Message(_("Member Address is required when enable corosync 
qdevice"))
+      end
+
       true
     end
 
@@ -759,8 +776,6 @@
       Cluster.corosync_qdevice = 
Convert.to_boolean(UI.QueryWidget(Id(:corosync_qdevice), :Value))
 
       Cluster.qdevice_model = UI.QueryWidget(Id(:qdevice_model), :Value)
-      Cluster.qdevice_votes = UI.QueryWidget(Id(:qdevice_votes), :Value).to_s
-
       Cluster.qdevice_host = UI.QueryWidget(Id(:qdevice_host), :Value)
       Cluster.qdevice_port = UI.QueryWidget(Id(:qdevice_port), :Value).to_s
       Cluster.qdevice_tls = UI.QueryWidget(Id(:qdevice_tls), :Value)
@@ -771,15 +786,12 @@
 
     def CorosyncQdeviceLayout
       qdevice_section = VBox(
-        HBox(
-          ComboBox(
-            Id(:qdevice_model),
-            Opt(:hstretch),
-            _("Qdevice model:"),
-            ["net"]
-          ),
-          Left(InputField(Id(:qdevice_votes),Opt(:hstretch), _("Qdevice 
votes:"),""))
-        )
+        Left(ComboBox(
+          Id(:qdevice_model),
+          Opt(:hstretch),
+          _("Qdevice model:"),
+          ["net"]
+        ))
       )
 
       qdevice_net_section = VBox(
@@ -793,13 +805,7 @@
             Id(:qdevice_tls), Opt(:hstretch), _("TLS:"),
             ["off", "on", "required"]
           )),
-          Left(ComboBox(
-            Id(:qdevice_algorithm), Opt(:hstretch, :notify), _("Algorithm:"),
-            [
-              Item(Id("ffsplit"), "ffsplit"),
-              Item(Id("lms"), "lms")
-            ]
-          )),
+          Left(ComboBox(Id(:qdevice_algorithm),Opt(:hstretch, :notify), 
_("Algorithm:"),["ffsplit"])),
           HSpacing(1),
           Left(InputField(Id(:qdevice_tie_breaker),Opt(:hstretch), _("Tie 
breaker:"),"lowest"))
         )
@@ -813,9 +819,7 @@
           _("En&able Corosync Qdevice"),
           false,
           VBox(
-            VSpacing(1),
             qdevice_section,
-            VSpacing(2),
             qdevice_net_section,
           )
         ),
@@ -827,13 +831,15 @@
       UI.ChangeWidget(Id(:corosync_qdevice), :Value, Cluster.corosync_qdevice)
 
       UI.ChangeWidget(Id(:qdevice_model), :Value, Cluster.qdevice_model)
-      UI.ChangeWidget(Id(:qdevice_votes), :Value, Cluster.qdevice_votes)
-      UI.ChangeWidget(Id(:qdevice_votes), :ValidChars, "0123456789");
 
       UI.ChangeWidget(Id(:qdevice_host), :Value, Cluster.qdevice_host)
       UI.ChangeWidget(Id(:qdevice_port), :Value, Cluster.qdevice_port)
       UI.ChangeWidget(Id(:qdevice_tls), :Value, Cluster.qdevice_tls)
       UI.ChangeWidget(Id(:qdevice_algorithm), :Value, 
Cluster.qdevice_algorithm)
+      # As for now, ffsplit is only can be configuried withing Yast (sync with 
crmsh)
+      if UI.QueryWidget(Id(:qdevice_algorithm), :Value) == "ffsplit"
+        Cluster.qdevice_votes = "1"
+      end
       UI.ChangeWidget(Id(:qdevice_tie_breaker), :Value, 
Cluster.qdevice_tie_breaker)
 
       nil
@@ -857,7 +863,6 @@
       CorosyncQdeviceLayout()
 
       while true
-        UpdateQdeviceVotes()
 
         ret = UI.UserInput
 
@@ -1010,22 +1015,49 @@
     end
 
     def UpdateServiceStatus
-      ret = 0
-      ret = Service.Status("pacemaker")
-      if ret == 0
+      ret_pacemaker = 0
+      ret_qdevice = 0
+      ret_pacemaker = Service.Status("pacemaker")
+      if Cluster.corosync_qdevice && ret_pacemaker == 0
+        ret_qdevice = Service.Status("corosync-qdevice")
+        # corosync-qdevice stop/start
+        if ret_qdevice == 0
+          UI.ChangeWidget(Id(:status_qdevice), :Value, _("Running"))
+          UI.ChangeWidget(Id("start_qdevice_now"), :Enabled, false)
+          UI.ChangeWidget(Id("stop_qdevice_now"), :Enabled, true)
+        else
+          UI.ChangeWidget(Id(:status_qdevice), :Value, _("Not running"))
+          UI.ChangeWidget(Id("start_qdevice_now"), :Enabled, true)
+          UI.ChangeWidget(Id("stop_qdevice_now"), :Enabled, false)
+        end
+      else
+        UI.ChangeWidget(Id(:status_qdevice), :Value, _("Not configured"))
+        UI.ChangeWidget(Id("start_qdevice_now"), :Enabled, false)
+        UI.ChangeWidget(Id("stop_qdevice_now"), :Enabled, false)
+      end
+      # pacemaker&corosync stop/start
+      if ret_pacemaker == 0
         UI.ChangeWidget(Id(:status), :Value, _("Running"))
+        UI.ChangeWidget(Id("start_now"), :Enabled, false)
+        UI.ChangeWidget(Id("stop_now"), :Enabled, true)
       else
         UI.ChangeWidget(Id(:status), :Value, _("Not running"))
+        UI.ChangeWidget(Id("start_now"), :Enabled, true)
+        UI.ChangeWidget(Id("stop_now"), :Enabled, false)
       end
-      UI.ChangeWidget(Id("start_now"), :Enabled, ret != 0)
-      UI.ChangeWidget(Id("stop_now"), :Enabled, ret == 0)
 
-      if not Service.Enabled("pacemaker")
-        UI.ChangeWidget(Id("off"), :Value, true)
-        UI.ChangeWidget(Id("on"), :Value, false)
+      ret_qdevice_booting = true
+      if Cluster.corosync_qdevice
+        ret_qdevice_booting = Service.Enabled("corosync-qdevice")
+      end
+      if Service.Enabled("pacemaker") && ret_qdevice_booting
+        UI.ChangeWidget(Id(:status_booting), :Value, _("Enabling"))
+        UI.ChangeWidget(Id("on"), :Enabled, false)
+        UI.ChangeWidget(Id("off"), :Enabled, true)
       else
-        UI.ChangeWidget(Id("on"), :Value, true)
-        UI.ChangeWidget(Id("off"), :Value, false)
+        UI.ChangeWidget(Id(:status_booting), :Value, _("Disabling"))
+        UI.ChangeWidget(Id("on"), :Enabled, true)
+        UI.ChangeWidget(Id("off"), :Enabled, false)
       end
 
       nil
@@ -1051,37 +1083,38 @@
       contents = VBox(
         VSpacing(1),
         Frame(
-          _("Booting"),
-          RadioButtonGroup(
-            Id("bootcorosync"),
-            HBox(
-              HSpacing(1),
-              VBox(
-                Left(
-                  RadioButton(
-                    Id("on"),
-                    Opt(:notify),
-                    _("On -- Start pacemaker during boot")
-                  )
-                ),
-                Left(
-                  RadioButton(
-                    Id("off"),
-                    Opt(:notify),
-                    _("Off -- Start pacemaker manually")
+          _("Cluster start at booting time enable/disable"),
+          Left(
+            VBox(
+              Left(
+                HBox(
+                  HSpacing(1),
+                  Label(_("Current Status: ")),
+                  Label(Id(:status_booting), _("Enabling")),
+                  ReplacePoint(Id("status_rp"), Empty())
+                )
+              ),
+              Left(
+                HBox(
+                  HSpacing(1),
+                  HBox(
+                    PushButton(Id("on"), _("Enable cluster")),
+                    PushButton(Id("off"), _("Disable cluster"))
                   )
                 )
               )
             )
           )
         ),
+
         VSpacing(1),
         Frame(
-          _("Switch On and Off"),
+          _("Pacemaker and corosync start/stop"),
           Left(
             VBox(
               Left(
                 HBox(
+                  HSpacing(1),
                   Label(_("Current Status: ")),
                   Label(Id(:status), _("Running")),
                   ReplacePoint(Id("status_rp"), Empty())
@@ -1091,8 +1124,33 @@
                 HBox(
                   HSpacing(1),
                   HBox(
-                    PushButton(Id("start_now"), _("Start pacemaker Now")),
-                    PushButton(Id("stop_now"), _("Stop pacemaker Now"))
+                    PushButton(Id("start_now"), _("Start Now")),
+                    PushButton(Id("stop_now"), _("Stop Now"))
+                  )
+                )
+              )
+            )
+          )
+        ),
+        VSpacing(1),
+        Frame(
+          _("corosync-qdevice start/stop"),
+          Left(
+            VBox(
+              Left(
+                HBox(
+                  HSpacing(1),
+                  Label(_("Current Status: ")),
+                  Label(Id(:status_qdevice), _("Running")),
+                  ReplacePoint(Id("status_rp_qdevice"), Empty())
+                )
+              ),
+              Left(
+                HBox(
+                  HSpacing(1),
+                  HBox(
+                    PushButton(Id("start_qdevice_now"), _("Start Now")),
+                    PushButton(Id("stop_qdevice_now"), _("Stop Now"))
                   )
                 )
               )
@@ -1118,30 +1176,51 @@
 
         if ret == "on"
           Service.Enable("pacemaker")
+          if Cluster.corosync_qdevice
+            Service.Enable("corosync-qdevice")
+          end
           next
         end
 
         if ret == "off"
           Service.Disable("pacemaker")
+          if Cluster.corosync_qdevice
+            Service.Disable("corosync-qdevice")
+          end
           next
         end
 
         # pacemaker will start corosync automatically.
-        # BNC#872651 is fixed, so stop pacemaker could stop corosync at the 
same time.
         if ret == "start_now"
           Cluster.save_csync2_conf
           Cluster.SaveClusterConfig
-          # BNC#872651 , add more info about error message
+          # BNC#872652 , add more info about error message
           Report.Error(Service.Error + errormsg) if !Service.Start("pacemaker")
           next
         end
+        # corosync-qdevice start
+        if ret == "start_qdevice_now"
+            Cluster.save_csync2_conf
+            Cluster.SaveClusterConfig
+            # reload the corosync.conf before starting qdevice within already 
started corosync
+            %x(corosync-cfgtool -R)
+            sleep(1)
+            Report.Error(Service.Error + errormsg) if 
!Service.Start("corosync-qdevice")
+            next
+        end
 
+        # pacemaker&corosync stop
         if ret == "stop_now"
           # BNC#874563,stop pacemaker could stop corosync since BNC#872651 is 
fixed
           # In bnc#1144200, the patch is dropped in corosync, so stop 
pacemaker not working
           Report.Error(Service.Error + errormsg) if !Service.Stop("corosync")
           next
         end
+        # corosync-qdevice stop
+        if ret == "stop_qdevice_now"
+          Report.Error(Service.Error + errormsg) if 
!Service.Stop("corosync-qdevice")
+          next
+        end
 
         if ret == :next || ret == :back
           val = ValidateService()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-cluster-4.2.4/src/include/cluster/helps.rb 
new/yast2-cluster-4.2.5/src/include/cluster/helps.rb
--- old/yast2-cluster-4.2.4/src/include/cluster/helps.rb        2019-09-27 
14:29:06.000000000 +0200
+++ new/yast2-cluster-4.2.5/src/include/cluster/helps.rb        2019-10-16 
05:12:19.000000000 +0200
@@ -33,6 +33,7 @@
       # All helps are here
       @HELPS = {
         "communication" => _(
+          "<p><b><big>IP Version</big></b><br>Specifies version of IP to use 
for communication. Value can be one of ipv4 or ipv6. Default (if unspecified) 
is ipv4.<br></p>\n" +
           "<p><b><big>Bind Network Address</big></b><br>This  specifies  the  
address which the openais executive should bind.  This address should always 
end in  zero.   If  the  totem traffic  should  be routed over 192.168.5.92, 
set bindnetaddr to 192.168.5.0.<br>This may also be an IPV6 address, in which 
case IPV6  networking will  be used.  In this case, the full address must be 
specified and there is no automatic selection  of  the  network  interface 
within a specific subnet as with IPv4. If IPv6 networking is used, the nodeid 
field must be specified.<br></p>\n" +
             "<p><b><big>Multicast Address</big></b><br>This is the multicast 
address used by  openais  executive.   The default  should work for most 
networks, but the network administrator should be queried  about  a  multicast  
address  to  use.  Avoid 224.x.x.x because this is a \"config\" multicast 
address.<br>This  may  also be an IPV6 multicast address, in which case IPV6 
networking will be used.  If IPv6 networking is used, the nodeid field must be 
specified.</p>\n" +
             "<p><b><big>Port</big></b><br>This  specifies  the UDP port 
number.  It is possible to use the same multicast address on a network with  
the  openais  services configured for different UDP ports.<br></p>\n" +
@@ -40,12 +41,11 @@
             "<p><b><big>Node ID</big></b><br>This  configuration  option  is  
optional  when  using  IPv4 and required when using IPv6.  This is a 32 bit 
value specifying the node identifier delivered to the cluster membership 
service.  If this is not specified with IPv4, the node id will be  determined 
from  the  32  bit  IP address the system to which the system is bound with 
ring identifier of 0.  The node identifier  value  of zero is reserved and 
should not be used.<br></p>\n" +
             "<p><b><big>rrp_mode</big></b><br>This specifies the mode of 
redundant ring, which  may  be  none, active,  or  passive.   Active 
replication offers slightly lower latency from transmit to delivery in faulty 
network environments but  with less performance.  Passive replication may 
nearly double the speed of the totem  protocol  if  the  protocol  doesn't 
become  cpu bound.  The final option is none, in which case only one network 
interface will be used to operate the  totem  protocol.  If  only one interface 
directive is specified, none is automatically chosen.  If multiple interface 
directives  are  specified, only active or passive may be chosen.<br></p>\n" +
             "<p><b><big>Cluster Name</big></b><br>This specifies the name of 
cluster and it's used for automatic generating of multicast address. Default is 
hacluster. For a geo cluster, each cluster must have a unique name.<br></p>\n" +
-            "<p><b><big>Expected votes</big></b><br>Expect vote number for 
voting quorum.  Will be automatically calculated when the nodelist {} section 
is present in corosync.conf (the list will be generated when using unicast 
transport) or can be specified in the quorum {} section (Expect votes should 
use the total node numble of the cluster). If Expected votes presents in 
unicast transport, the value will override the one automatically 
calculated.<br></p>\n" +
+            "<p><b><big>Expected votes</big></b><br>Expect vote number for 
voting quorum.  Will be automatically calculated when the nodelist {} section 
is present in corosync.conf (the list will be generated when using unicast 
transport) or can be specified in the quorum {} section (Expect votes should 
use the total node numble of the cluster). If Expected votes presents in 
unicast transport, the value will override the one automatically calculated. 
For safety, the Expected votes will be disabled once nodelist not empty, it's 
good for ignore the inappropriate Expected votes set.<br></p>\n" +
             "<p><b><big>Auto Generate Node ID</big></b><br>Nodeid is required 
when using IPv6. Auto node ID enabled will generate nodeid 
automatically.<br></p>\n"
         ),
         "corosyncqdevice"      => _(
           "<p><b><big>Model</big></b><br>Specifies the model to be used. This 
parameter is required.  corosync-qdevice is modular and is able to support 
multiple different models. The model basically defines what type of arbitrator 
is used. Currently only 'net' is supported.</p>\n" +
-            "<p><b><big>Votes</big></b><br>The number of votes provided to the 
cluster by qdevice. It should be configured as 1 when using 'ffsplit' algorithm 
and sum(votes_per_node) - 1 when 'lms' algorithm. Default is 1 or 
(number_of_nodes - 1) or generally sum(votes_per_node) - 1 based on 
algorithm.</p>\n" +
             "<p><b><big>Host</big></b><br>Specifies the IP address or host 
name of the qnetd server to be used. This parameter is required.</p>\n" +
             "<p><b><big>Port</big></b><br>Specifies TCP port of qnetd server. 
Default is 5403.</p>\n" +
             "<p><b><big>TLS</big></b><br>Can be one of 'on', 'off' or 
'required' and specifies if tls should be used. 'on' means a connection with 
TLS is attempted first, but if the server doesn't advertise TLS support then 
non-TLS will be used. 'off' is used then TLS is not required and it's then not 
even tried. This mode is the only one which doesn't need a properly initialized 
NSS database. 'required' means TLS is required and if the server doesn't 
support TLS, qdevice will exit with error message. 'on' need manually change, 
refer to corosync-qdevice's man page for more details. Default is 'off' in 
yast.</p>\n" +
@@ -58,7 +58,8 @@
         ),
         "service"       => _(
           "\n" +
-            "\t\t\t<p><b><big>Booting</big></b><br>Starting corosync service 
during boot or not</p>\n" +
+            "\t\t\t<p><b><big>Cluster start at booting time 
enable/disable</big></b><br>Start or not start the whole cluster at booting 
time. Service include: pacemaker, corosync, corosync-qdevice(If enabled 
corosyncqdevice).</p>\n" +
+            "\t\t\t<p><b><big>Cluster start/stop now</big></b><br>Start or 
stop the whole cluster right now. Service include: pacemaker, corosync, 
corosync-qdevice(If enabled corosyncqdevice).</p>\n" +
             "\t\t\t<p><b><big>Firewall Settings</big></b><br>Enable the port 
when Firewall is enabled</p>\n" +
             "\t\t\t"
         ),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-cluster-4.2.4/src/modules/Cluster.rb 
new/yast2-cluster-4.2.5/src/modules/Cluster.rb
--- old/yast2-cluster-4.2.4/src/modules/Cluster.rb      2019-09-27 
14:29:06.000000000 +0200
+++ new/yast2-cluster-4.2.5/src/modules/Cluster.rb      2019-10-16 
05:12:19.000000000 +0200
@@ -96,6 +96,7 @@
       # {:addr1=>"10.16.35.104",:nodeid=>"4" },
       # {:addr1=>"10.16.35.105",:nodeid=>"5" }]
       @memberaddr = []
+      @address = []
 
       @corosync_qdevice = false
 
@@ -200,17 +201,17 @@
 
       @transport = SCR.Read(path(".openais.totem.transport"))
       @transport = "udp" if @transport == nil
+      @address = SCR.Read(path(".openais.nodelist.node")).split(" ")
 
       interfaces = SCR.Dir(path(".openais.totem.interface"))
       Builtins.foreach(interfaces) do |interface|
         if interface == "interface0"
-          if @transport == "udpu"
+          if @address != []
             # BNC#871970, change member addresses to nodelist structure
             # memberaddr of udpu only read in interface0
             # address is like "123.3.21.32;156.32.123.1:1 
123.3.21.54;156.32.123.4:2 
             # 123.3.21.44;156.32.123.9"
-            address = SCR.Read(path(".openais.nodelist.node")).split(" ")
-            address.each do |addr|
+            @address.each do |addr|
               p = addr.split("-")
               if p[1] != nil
                 q = p[0].split(";")
@@ -228,8 +229,9 @@
                 end
               end
             end  # end address.each 
+          end
 
-          else
+          if @transport == "udp"
             @mcastaddr1 = Convert.to_string(
               SCR.Read(path(".openais.totem.interface.interface0.mcastaddr"))
             )
@@ -321,28 +323,34 @@
       SCR.Write(path(".openais.totem.transport"), @transport)
       SCR.Write(path(".openais.totem.cluster_name"), @cluster_name)
       SCR.Write(path(".openais.totem.ip_version"), @ip_version)
-      if @expected_votes != ""
-        SCR.Write(path(".openais.quorum.expected_votes"), @expected_votes)
-      end
+      SCR.Write(path(".openais.quorum.expected_votes"), @expected_votes)
 
       # BNC#871970, only write member address when interface0  
-      if @transport == "udpu"
+      if @memberaddr != []
 
         SCR.Write(
           path(".openais.nodelist.node"),
           generateMemberString(@memberaddr)
         )
-        SCR.Write(path(".openais.totem.interface.interface0.mcastaddr"), "")
       else
+        SCR.Write(path(".openais.nodelist.node"), "")
+      end
+      if @transport == "udp"
         SCR.Write(
           path(".openais.totem.interface.interface0.mcastaddr"),
           @mcastaddr1
         )
-        SCR.Write(path(".openais.nodelist.node"), "")
+        SCR.Write(
+          path(".openais.totem.interface.interface0.bindnetaddr"),
+          @bindnetaddr1
+        )
+      else
+        SCR.Write(path(".openais.totem.interface.interface0.mcastaddr"), "")
+        SCR.Write(path(".openais.totem.interface.interface0.bindnetaddr"), "")
       end
 
       # BNC#883235. Enable "two_node" when using two node cluster
-      if (@expected_votes == "2") or (@transport == "udpu" && @memberaddr.size 
== 2)
+      if ((@expected_votes == "2") or (@memberaddr.size == 2)) and 
(!@corosync_qdevice)
         # Set "1" to enable two_node mode when two nodes, otherwise is "0".
         @two_node = "1"
       end
@@ -354,10 +362,6 @@
       SCR.Write(path(".openais.quorum.two_node"), @two_node)
 
       SCR.Write(
-        path(".openais.totem.interface.interface0.bindnetaddr"),
-        @bindnetaddr1
-      )
-      SCR.Write(
         path(".openais.totem.interface.interface0.mcastport"),
         @mcastport1
       )
@@ -490,7 +494,8 @@
         "csync2",
         "conntrack-tools",
         "hawk2",
-        "crmsh"
+        "crmsh",
+        "corosync-qdevice"
       ]
       ret = 
PackageSystem.CheckAndInstallPackagesInteractive(required_pack_list)
       if ret == false
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-cluster-4.2.4/src/servers_non_y2/ag_openais 
new/yast2-cluster-4.2.5/src/servers_non_y2/ag_openais
--- old/yast2-cluster-4.2.4/src/servers_non_y2/ag_openais       2019-09-27 
14:29:06.000000000 +0200
+++ new/yast2-cluster-4.2.5/src/servers_non_y2/ag_openais       2019-10-16 
05:12:19.000000000 +0200
@@ -65,9 +65,6 @@
        "rrp_mode":{"doc":"The mode for redundant ring. None is used when only 
1 interface specified, otherwise, only active or passive may be choosen",
                    "type":"select[none,active,passive]", 
"default_value":"none"},
        "netmtu":{"doc":"Size of MTU", "type":"int", "default_value":1500},
-       "vsftype":{"doc":"The virtual synchrony filter type used to indentify a 
primary component. Change with care.",
-                  "default_value":"ykd",
-                  "suggested_value":"none"},
        "token":{"doc":"Timeout for a token lost. in ms",
                 "type":"int", "default_value":1000,
                 "suggested_value":5000},
@@ -170,7 +167,7 @@
                "model":{"doc":"Specifies the model to be used, currently only 
(net) is 
supported.","type":"string","default_value":"net","suggested_value":"net"},
                "timeout":{"doc":"Specifies how often corosync-qdevice should 
call the votequorum_poll 
function.","type":"int","default_value":10000,"suggested_value":10000},
                "sync_timeout":{"doc":"Specifies how often corosync-qdevice 
should call the votequorum_poll function during a sync 
phase.","type":"int","default_value":30000,"suggested_value":30000},
-               "votes":{"doc":"The number of votes provided to the cluster by 
qdevice. Default is sum(votes_per_node) - 1.","type":"int","default_value":0}
+               "votes":{"doc":"The number of votes provided to the cluster by 
qdevice. Default is sum(votes_per_node) - 1.","type":"int","default_value":1}
                }
 
 quorum_qdevice_net_option_table = {
@@ -270,8 +267,9 @@
                                        f.write("\t\t%s:\t%s\n\n" % (l, 
quorum_qdevice_options[l]))
                        f.write("\t}\n")
                else:
-                       f.write("\t#%s\n" % (quorum_option_table[key]["doc"]))
-                       f.write("\t%s:\t%s\n\n" % (key, quorum_options[key]))
+                       if quorum_options[key] != "":
+                               f.write("\t#%s\n" % 
(quorum_option_table[key]["doc"]))
+                               f.write("\t%s:\t%s\n\n" % (key, 
quorum_options[key]))
        f.write("}\n")
 
 def print_qb_options(f):
@@ -314,7 +312,7 @@
                        for log in logging_options["logger_subsys"]:
                                f.write("\tlogger_subsys {\n")
                                for l in log.keys():
-                                       f.write("\t\t#%s\n\n" % 
(logger_subsys_option_table[l]["doc"]))
+                                       f.write("\t\t#%s\n" % 
(logger_subsys_option_table[l]["doc"]))
                                        f.write("\t\t%s:\t%s\n\n" % (l, log[l]))
                                f.write("\t}\n")
                else:


Reply via email to