Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package crmsh for openSUSE:Factory checked 
in at 2025-06-23 15:06:19
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/crmsh (Old)
 and      /work/SRC/openSUSE:Factory/.crmsh.new.7067 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "crmsh"

Mon Jun 23 15:06:19 2025 rev:376 rq:1287917 version:5.0.0+20250623.50ad8e8f

Changes:
--------
--- /work/SRC/openSUSE:Factory/crmsh/crmsh.changes      2025-06-20 
16:50:59.656193125 +0200
+++ /work/SRC/openSUSE:Factory/.crmsh.new.7067/crmsh.changes    2025-06-23 
15:07:24.003057911 +0200
@@ -1,0 +2,13 @@
+Mon Jun 23 11:41:49 UTC 2025 - xli...@suse.com
+
+- Update to version 5.0.0+20250623.50ad8e8f:
+  * Dev: unittests: Adjust unit test for previous commit
+  * Fix: crash_test: Correctly retrieve fence event information (bsc#1243786)
+
+-------------------------------------------------------------------
+Mon Jun 23 03:11:08 UTC 2025 - xli...@suse.com
+
+- Update to version 5.0.0+20250623.b760f655:
+  * Dev: run-functional-tests: Fetch container's IP address correctly
+
+-------------------------------------------------------------------

Old:
----
  crmsh-5.0.0+20250619.5d3fc833.tar.bz2

New:
----
  crmsh-5.0.0+20250623.50ad8e8f.tar.bz2

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

Other differences:
------------------
++++++ crmsh.spec ++++++
--- /var/tmp/diff_new_pack.RBNodP/_old  2025-06-23 15:07:26.379157004 +0200
+++ /var/tmp/diff_new_pack.RBNodP/_new  2025-06-23 15:07:26.379157004 +0200
@@ -41,7 +41,7 @@
 Summary:        High Availability cluster command-line interface
 License:        GPL-2.0-or-later
 Group:          %{pkg_group}
-Version:        5.0.0+20250619.5d3fc833
+Version:        5.0.0+20250623.50ad8e8f
 Release:        0
 URL:            http://crmsh.github.io
 Source0:        %{name}-%{version}.tar.bz2

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.RBNodP/_old  2025-06-23 15:07:26.423158840 +0200
+++ /var/tmp/diff_new_pack.RBNodP/_new  2025-06-23 15:07:26.427159006 +0200
@@ -9,7 +9,7 @@
 </service>
 <service name="tar_scm">
   <param name="url">https://github.com/ClusterLabs/crmsh.git</param>
-  <param 
name="changesrevision">5d3fc8332df0226b8c6af6a9150204210aaae7d7</param>
+  <param 
name="changesrevision">50ad8e8fb153c925641f693a5f056f82e5a9c8a1</param>
 </service>
 </servicedata>
 (No newline at EOF)

++++++ crmsh-5.0.0+20250619.5d3fc833.tar.bz2 -> 
crmsh-5.0.0+20250623.50ad8e8f.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-5.0.0+20250619.5d3fc833/crmsh/crash_test/config.py 
new/crmsh-5.0.0+20250623.50ad8e8f/crmsh/crash_test/config.py
--- old/crmsh-5.0.0+20250619.5d3fc833/crmsh/crash_test/config.py        
2025-06-19 11:43:52.000000000 +0200
+++ new/crmsh-5.0.0+20250623.50ad8e8f/crmsh/crash_test/config.py        
2025-06-23 13:15:35.000000000 +0200
@@ -4,6 +4,5 @@
               iptables -{action} OUTPUT -d {peer_ip} -j DROP'''
 REMOVE_PORT = "firewall-cmd --zone=public --remove-port={port}/udp"
 ADD_PORT = "firewall-cmd --zone=public --add-port={port}/udp"
-FENCE_HISTORY = "stonith_admin -h {node}"
 SBD_CONF = "/etc/sysconfig/sbd"
 SBD_CHECK_CMD = "sbd -d {dev} dump"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-5.0.0+20250619.5d3fc833/crmsh/crash_test/task.py 
new/crmsh-5.0.0+20250623.50ad8e8f/crmsh/crash_test/task.py
--- old/crmsh-5.0.0+20250619.5d3fc833/crmsh/crash_test/task.py  2025-06-19 
11:43:52.000000000 +0200
+++ new/crmsh-5.0.0+20250623.50ad8e8f/crmsh/crash_test/task.py  2025-06-23 
13:15:35.000000000 +0200
@@ -1,11 +1,12 @@
 import os
-import re
 import time
 import threading
 import shutil
 import tempfile
+from datetime import datetime
 from contextlib import contextmanager
 from crmsh import utils as crmshutils
+from crmsh import xmlutil
 from crmsh import log
 from . import utils
 from . import config
@@ -27,6 +28,7 @@
     REBOOT_WARNING = """!!! WARNING WARNING WARNING !!!
 THIS CASE MAY LEAD TO NODE BE FENCED.
 TYPE Yes TO CONTINUE, OTHER INPUTS WILL CANCEL THIS CASE [Yes/No](No): """
+    TIME_STR_FORMAT = '%Y/%m/%d %H:%M:%S'
 
     def __init__(self, description, flush=False, quiet=False):
         """
@@ -37,7 +39,7 @@
         self.force = False
         self.quiet = quiet
         self.messages = []
-        self.timestamp = utils.now()
+        self.timestamp = datetime.now()
         self.description = description
         utils.msg_info(self.description, to_stdout=False)
         self.flush = flush
@@ -81,7 +83,7 @@
         Build base results
         """
         self.result = {
-            "Timestamp": self.timestamp,
+            "Timestamp": self.timestamp.strftime(self.TIME_STR_FORMAT),
             "Description": self.description,
             "Messages": ["{} {}:{}".format(m[2], m[0].upper(), m[1])
                          for m in self.messages]
@@ -128,36 +130,24 @@
         1. There is one latest fence action successfully done
         2. No fence action during fence timeout, thread_stop_event triggered 
by main thread
         """
-        target_node = None
-        from_node = None
-        fence_timestamp = None
-
         # Try to find out which node fire the fence action
         while not self.thread_stop_event.is_set():
-            rc, out, _ = ShellUtils().get_stdout_stderr("crm_mon -1|grep -A1 
\"Fencing Actions:\"")
-            if rc == 0 and out:
-                match = re.search(r"of (.*) pending: .*origin=(.*)$", out)
-                if match:
-                    target_node, from_node = match.groups()
-                    self.info("Node \"{}\" will be fenced by 
\"{}\"!".format(target_node, from_node))
+            fence_event_dict = 
xmlutil.CrmMonXmlParser().get_last_fence_event_info()
+            if fence_event_dict:
+                target_node = fence_event_dict.get('target')
+                origin_node = fence_event_dict.get('origin')
+                complete_time = fence_event_dict.get('completed')
+                status = fence_event_dict.get('status')
+                if status == "pending" and not self.fence_start_event.is_set():
+                    self.info(f"Node \"{target_node}\" will be fenced by 
\"{origin_node}\"!")
                     self.fence_start_event.set()
-                    break
-            time.sleep(1)
-
-        # Try to find out proof that fence happened
-        while not self.thread_stop_event.is_set():
-            rc, out, _ = 
ShellUtils().get_stdout_stderr(config.FENCE_HISTORY.format(node=target_node))
-            if rc == 0 and out:
-                match = re.search(r"Node {} last fenced at: 
(.*)".format(target_node), out)
-                if match:
-                    fence_timestamp = match.group(1)
-                    task_timestamp_dt = utils.str_to_datetime(self.timestamp, 
'%Y/%m/%d %H:%M:%S')
-                    fence_timestamp_dt = 
utils.str_to_datetime(fence_timestamp, '%a %b %d %H:%M:%S %Y')
-                    # If the fence action timestamp larger than this task's 
timestamp
-                    # That is the proof
-                    if task_timestamp_dt < fence_timestamp_dt:
-                        self.info("Node \"{}\" was successfully fenced by 
\"{}\"".format(target_node, from_node))
-                        # Tell main thread fence happened
+                # Try to find out proof that fence happened
+                elif status == "success":
+                    task_timestamp = self.timestamp.timestamp()
+                    complete_timestamp = 
datetime.fromisoformat(complete_time).timestamp()
+                    # This success event should after the task started
+                    if task_timestamp < complete_timestamp:
+                        self.info(f"Node \"{target_node}\" was fenced by 
\"{origin_node}\" at {complete_time}")
                         self.fence_finish_event.set()
                         break
             time.sleep(1)
@@ -259,7 +249,7 @@
                 message = "{} [{}]".format(self.description, utils.CGREEN + 
"Pass" + utils.CEND)
             else:
                 message = "{} [{}]".format(self.description, utils.CRED + 
"Fail" + utils.CEND)
-            logger.info(message, extra={'timestamp': 
'[{}]'.format(self.timestamp)})
+            logger.info(message, extra={'timestamp': 
'[{}]'.format(self.timestamp.strftime(self.TIME_STR_FORMAT))})
 
             for msg in self.messages:
                 logger.log(utils.LEVEL[msg[0]], msg[1], extra={'timestamp': '  
'})
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/crmsh-5.0.0+20250619.5d3fc833/crmsh/xmlutil.py 
new/crmsh-5.0.0+20250623.50ad8e8f/crmsh/xmlutil.py
--- old/crmsh-5.0.0+20250619.5d3fc833/crmsh/xmlutil.py  2025-06-19 
11:43:52.000000000 +0200
+++ new/crmsh-5.0.0+20250623.50ad8e8f/crmsh/xmlutil.py  2025-06-23 
13:15:35.000000000 +0200
@@ -1574,4 +1574,19 @@
         """
         xpath = f'//resource[@resource_agent="{ra_type}"]'
         return [elem.get('id') for elem in self.xml_elem.xpath(xpath)]
+
+    def get_last_fence_event_info(self) -> dict:
+        fence_event_info = {}
+        fence_events = self.xml_elem.xpath(r'//fence_history/fence_event')
+        if not fence_events:
+            return fence_event_info
+        last_event = fence_events[0]
+        fence_event_info = {
+            'origin': last_event.get('origin', ''),
+            'target': last_event.get('target', ''),
+            'action': last_event.get('action', ''),
+            'status': last_event.get('status', ''),
+            'completed': last_event.get('completed', '')
+        }
+        return fence_event_info
 # vim:ts=4:sw=4:et:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-5.0.0+20250619.5d3fc833/test/run-functional-tests 
new/crmsh-5.0.0+20250623.50ad8e8f/test/run-functional-tests
--- old/crmsh-5.0.0+20250619.5d3fc833/test/run-functional-tests 2025-06-19 
11:43:52.000000000 +0200
+++ new/crmsh-5.0.0+20250623.50ad8e8f/test/run-functional-tests 2025-06-23 
13:15:35.000000000 +0200
@@ -246,7 +246,10 @@
 config_cluster() {
        node_num=$#
        insert_str=""
-       container_ip_array=(`podman network inspect $HA_NETWORK_ARRAY -f 
'{{range .Containers}}{{printf "%s " .IPv4Address}}{{end}}'`)
+       for node in $*;do
+               ip=`podman container inspect $node -f 
"{{.NetworkSettings.Networks.$HA_NETWORK_ARRAY.IPAddress}}"|tr -d "\r"`
+               container_ip_array+=($ip)
+       done
 
        for i in $(seq $node_num -1 1);do
                ip=`echo ${container_ip_array[$((i-1))]}|awk -F/ '{print $1}'`
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-5.0.0+20250619.5d3fc833/test/unittests/test_crashtest_task.py 
new/crmsh-5.0.0+20250623.50ad8e8f/test/unittests/test_crashtest_task.py
--- old/crmsh-5.0.0+20250619.5d3fc833/test/unittests/test_crashtest_task.py     
2025-06-19 11:43:52.000000000 +0200
+++ new/crmsh-5.0.0+20250623.50ad8e8f/test/unittests/test_crashtest_task.py     
2025-06-23 13:15:35.000000000 +0200
@@ -203,14 +203,14 @@
         """
 
     @mock.patch('crmsh.crash_test.utils.msg_info')
-    @mock.patch('crmsh.crash_test.utils.now')
-    def setUp(self, mock_now, mock_msg_info):
+    def setUp(self, mock_msg_info):
         """
         Test setUp.
         """
-        mock_now.return_value = "2019/07/10 01:15:15"
+        fake_timedate = datetime(2019, 7, 10, 1, 15, 15)
         main.ctx = mock.Mock(task_list=[{"process_name": "xin", "age": 38}])
         self.task_check_inst = task.TaskCheck("task check job1", quiet=False)
+        self.task_check_inst.timestamp = fake_timedate
         self.task_check_inst_quiet = task.TaskCheck("task check job1", 
quiet=True)
 
     def tearDown(self):
@@ -559,15 +559,14 @@
         """
 
     @mock.patch('crmsh.crash_test.utils.msg_info')
-    @mock.patch('crmsh.crash_test.utils.now')
-    def setUp(self, mock_now, mock_info):
+    def setUp(self, mock_info):
         """
         Test setUp.
         """
-        mock_now.return_value = "2019/07/10 01:15:15"
+        fake_now = datetime(2019, 7, 10, 1, 15, 15)
         main.ctx = mock.Mock(task_list={"process_name": "xin", "age": 38})
         self.task_inst = task.Task("task description", flush=True)
-        mock_now.assert_called_once_with()
+        self.task_inst.timestamp = fake_now
 
     def tearDown(self):
         """
@@ -647,7 +646,7 @@
     def test_build_base_result(self):
         self.task_inst.build_base_result()
         expected_result = {
-            "Timestamp": self.task_inst.timestamp,
+            "Timestamp": '2019/07/10 01:15:15',
             "Description": self.task_inst.description,
             "Messages": []
         }
@@ -666,45 +665,33 @@
         mock_ask.assert_called_once_with(task.Task.REBOOT_WARNING)
         self.task_inst.info.assert_called_once_with("Testcase cancelled")
 
-    @mock.patch('crmsh.crash_test.utils.str_to_datetime')
     @mock.patch('time.sleep')
     @mock.patch('crmsh.crash_test.task.Task.info')
-    @mock.patch('crmsh.sh.ShellUtils.get_stdout_stderr')
-    def test_fence_action_monitor(self, mock_run, mock_info, mock_sleep, 
mock_datetime):
+    @mock.patch('crmsh.xmlutil.CrmMonXmlParser')
+    def test_fence_action_monitor(self, mock_parser, mock_info, mock_sleep):
         self.task_inst.thread_stop_event = mock.Mock()
-        self.task_inst.thread_stop_event.is_set.side_effect = [False, False, 
False, False]
+        self.task_inst.thread_stop_event.is_set.side_effect = [False, False]
         self.task_inst.fence_start_event = mock.Mock()
+        self.task_inst.fence_start_event.is_set.side_effect = [False, True]
         self.task_inst.fence_finish_event = mock.Mock()
-        output = "Pending Fencing Actions:\n  * reboot of 15sp2-2 pending: 
client=pacemaker-controld.2430, origin=15sp2-1"
-        output2 = "Node 15sp2-2 last fenced at: Tue Jan 19 16:08:37 2021"
-        mock_run.side_effect = [(1, None, None), (0, output, None), (1, None, 
None), (0, output2, None)]
-        self.task_inst.timestamp = "2021/01/19 16:08:24"
-        mock_datetime.side_effect = [
-            datetime.strptime(self.task_inst.timestamp, '%Y/%m/%d %H:%M:%S'),
-            datetime.strptime("Tue Jan 19 16:08:37 2021", '%a %b %d %H:%M:%S 
%Y')
+        mock_parser_inst = mock.Mock()
+        mock_parser.return_value = mock_parser_inst
+        mock_parser_inst.get_last_fence_event_info.side_effect = [
+            {"target": "node2", "origin": "node1", "status": "pending", 
"completed": ""},
+            {"target": "node2", "origin": "node1", "status": "success", 
"completed": "2025-05-30 10:41:58.376958 +08:00"},
         ]
 
         self.task_inst.fence_action_monitor()
 
-        self.task_inst.thread_stop_event.is_set.assert_has_calls([
-            mock.call(),
-            mock.call(),
-            mock.call(),
-            mock.call()
-            ])
-        mock_run.assert_has_calls([
-            mock.call("crm_mon -1|grep -A1 \"Fencing Actions:\""),
-            mock.call("crm_mon -1|grep -A1 \"Fencing Actions:\""),
-            mock.call(config.FENCE_HISTORY.format(node="15sp2-2")),
-            mock.call(config.FENCE_HISTORY.format(node="15sp2-2"))
-            ])
+        self.task_inst.thread_stop_event.is_set.assert_has_calls([mock.call(), 
mock.call()])
         mock_info.assert_has_calls([
-            mock.call("Node \"15sp2-2\" will be fenced by \"15sp2-1\"!"),
-            mock.call("Node \"15sp2-2\" was successfully fenced by 
\"15sp2-1\"")
+            mock.call("Node \"node2\" will be fenced by \"node1\"!"),
+            mock.call("Node \"node2\" was fenced by \"node1\" at 2025-05-30 
10:41:58.376958 +08:00")
             ])
         self.task_inst.fence_start_event.set.assert_called_once_with()
         self.task_inst.fence_finish_event.set.assert_called_once_with()
 
+
 class TestFixSBD(TestCase):
     """
     Class to test TaskFixSBD of task.py

Reply via email to