Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package crmsh for openSUSE:Factory checked 
in at 2023-04-27 20:00:36
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/crmsh (Old)
 and      /work/SRC/openSUSE:Factory/.crmsh.new.1533 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "crmsh"

Thu Apr 27 20:00:36 2023 rev:293 rq:1083164 version:4.5.0+20230427.11d11104

Changes:
--------
--- /work/SRC/openSUSE:Factory/crmsh/crmsh.changes      2023-04-24 
22:31:53.791754332 +0200
+++ /work/SRC/openSUSE:Factory/.crmsh.new.1533/crmsh.changes    2023-04-27 
20:00:54.141914195 +0200
@@ -1,0 +2,15 @@
+Thu Apr 27 06:35:41 UTC 2023 - xli...@suse.com
+
+- Update to version 4.5.0+20230427.11d11104:
+  * Dev: behave: Add <user>@ when joining for non-root case
+  * Dev: behave: Add functional test for bsc#1210693
+
+-------------------------------------------------------------------
+Wed Apr 26 14:28:37 UTC 2023 - xli...@suse.com
+
+- Update to version 4.5.0+20230426.b7c4b1aa:
+  * Dev: behave: Adjust functional test for previous change
+  * Dev: unittest: adjust unit tests for previous changes
+  * Fix: bootstrap: crm cluster join default behavior change in ssh key 
handling (bsc#1210693)
+
+-------------------------------------------------------------------

Old:
----
  crmsh-4.5.0+20230424.75600b3f.tar.bz2

New:
----
  crmsh-4.5.0+20230427.11d11104.tar.bz2

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

Other differences:
------------------
++++++ crmsh.spec ++++++
--- /var/tmp/diff_new_pack.qUF42E/_old  2023-04-27 20:00:54.701917487 +0200
+++ /var/tmp/diff_new_pack.qUF42E/_new  2023-04-27 20:00:54.705917510 +0200
@@ -36,7 +36,7 @@
 Summary:        High Availability cluster command-line interface
 License:        GPL-2.0-or-later
 Group:          %{pkg_group}
-Version:        4.5.0+20230424.75600b3f
+Version:        4.5.0+20230427.11d11104
 Release:        0
 URL:            http://crmsh.github.io
 Source0:        %{name}-%{version}.tar.bz2

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.qUF42E/_old  2023-04-27 20:00:54.749917768 +0200
+++ /var/tmp/diff_new_pack.qUF42E/_new  2023-04-27 20:00:54.753917792 +0200
@@ -9,7 +9,7 @@
 </service>
 <service name="tar_scm">
   <param name="url">https://github.com/ClusterLabs/crmsh.git</param>
-  <param 
name="changesrevision">75600b3f641bdcc21b2252080700e71d17e1d03a</param>
+  <param 
name="changesrevision">03886aa3a42cdc817f65bcf88eaffc75a4d6845d</param>
 </service>
 </servicedata>
 (No newline at EOF)

++++++ crmsh-4.5.0+20230424.75600b3f.tar.bz2 -> 
crmsh-4.5.0+20230427.11d11104.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/crmsh-4.5.0+20230424.75600b3f/crmsh/bootstrap.py 
new/crmsh-4.5.0+20230427.11d11104/crmsh/bootstrap.py
--- old/crmsh-4.5.0+20230424.75600b3f/crmsh/bootstrap.py        2023-04-24 
10:59:23.000000000 +0200
+++ new/crmsh-4.5.0+20230427.11d11104/crmsh/bootstrap.py        2023-04-27 
08:13:57.000000000 +0200
@@ -187,17 +187,11 @@
             else:
                 utils.fatal("Unsupported config: local node is using root and 
remote nodes is using non-root users.")
         elif users_of_specified_hosts == 'not_specified':
-            if has_sudoer:
-                self.current_user = sudoer
-            else:
-                assert userdir.getuser() == 'root'
-                self.current_user = 'root'
+            assert userdir.getuser() == 'root'
+            self.current_user = 'root'
         elif users_of_specified_hosts == 'no_hosts':
-            if has_sudoer:
-                self.current_user = sudoer
-            else:
-                assert userdir.getuser() == 'root'
-                self.current_user = 'root'
+            assert userdir.getuser() == 'root'
+            self.current_user = 'root'
         else:
             raise AssertionError('Bad parameter user_of_specified_hosts: 
{}'.format(users_of_specified_hosts))
 
@@ -872,9 +866,6 @@
 
     # If not use -N/--nodes option
     if not node_list:
-        user_by_host = utils.HostUserConfig()
-        user_by_host.add(local_user, utils.this_node())
-        user_by_host.save_local()
         return
 
     print()
@@ -1635,22 +1626,31 @@
     if qdevice_inst.ssh_user is not None:
         # if the remote user is specified explicitly, use it
         ssh_user = qdevice_inst.ssh_user
+        local_user = utils.UserOfHost.instance().user_of(utils.this_node())
     else:
         try:
             # if ssh session has ready been available, use that
             local_user, ssh_user = 
utils.UserOfHost.instance().user_pair_for_ssh(qnetd_addr)
         except utils.UserOfHost.UserNotFoundError:
             pass
-    if local_user is None:
-        local_user = userdir.get_sudoer()
-        if local_user is None:
-            local_user = userdir.getuser()
     if ssh_user is None:
+        local_user = userdir.get_sudoer()
         ssh_user = local_user
     # Configure ssh passwordless to qnetd if detect password is needed
     if utils.check_ssh_passwd_need(local_user, ssh_user, qnetd_addr):
         configure_ssh_key(local_user)
-        utils.ssh_copy_id(local_user, ssh_user, qnetd_addr)
+        if 0 != utils.ssh_copy_id_no_raise(local_user, ssh_user, qnetd_addr):
+            msg = f"Failed to login to {ssh_user}@{qnetd_addr}. Please check 
the credentials."
+            sudoer = userdir.get_sudoer()
+            if sudoer and ssh_user != sudoer:
+                args = ['sudo crm']
+                args += [x for x in sys.argv[1:]]
+                for i, arg in enumerate(args):
+                    if arg == '--qnetd-hostname' and i + 1 < len(args):
+                        if '@' not in args[i + 1]:
+                            args[i + 1] = f'{sudoer}@{qnetd_addr}'
+                            msg += '\nOr, run "{}".'.format(' '.join(args))
+            raise ValueError(msg)
     user_by_host = utils.HostUserConfig()
     user_by_host.add(ssh_user, qnetd_addr)
     user_by_host.save_remote(cluster_node_list)
@@ -1692,7 +1692,18 @@
     local_user = _context.current_user
     utils.start_service("sshd.service", enable=True)
     configure_ssh_key(local_user)
-    utils.ssh_copy_id(local_user, seed_user, seed_host)
+    if 0 != utils.ssh_copy_id_no_raise(local_user, seed_user, seed_host):
+        msg = f"Failed to login to {seed_user}@{seed_host}. Please check the 
credentials."
+        sudoer = userdir.get_sudoer()
+        if sudoer and seed_user != sudoer:
+            args = ['sudo crm']
+            args += [x for x in sys.argv[1:]]
+            for i, arg in enumerate(args):
+                if arg == '-c' or arg == '--cluster-node' and i + 1 < 
len(args):
+                    if '@' not in args[i+1]:
+                        args[i + 1] = f'{sudoer}@{seed_host}'
+                        msg += '\nOr, run "{}".'.format(' '.join(args))
+        raise ValueError(msg)
     # After this, login to remote_node is passwordless
     swap_public_ssh_key(seed_host, local_user, seed_user, local_user, 
seed_user, add=True)
     configure_ssh_key('hacluster')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/crmsh-4.5.0+20230424.75600b3f/crmsh/ui_cluster.py 
new/crmsh-4.5.0+20230427.11d11104/crmsh/ui_cluster.py
--- old/crmsh-4.5.0+20230424.75600b3f/crmsh/ui_cluster.py       2023-04-24 
10:59:23.000000000 +0200
+++ new/crmsh-4.5.0+20230427.11d11104/crmsh/ui_cluster.py       2023-04-27 
08:13:57.000000000 +0200
@@ -317,8 +317,8 @@
                                    help="Configure corosync use IPv6")
 
         qdevice_group = parser.add_argument_group("QDevice configuration", 
re.sub('  ', '', constants.QDEVICE_HELP_INFO) + "\n\nOptions for configuring 
QDevice and QNetd.")
-        qdevice_group.add_argument("--qnetd-hostname", dest="qnetd_addr", 
metavar="HOST",
-                                   help="HOST or IP of the QNetd server to be 
used")
+        qdevice_group.add_argument("--qnetd-hostname", dest="qnetd_addr", 
metavar="[USER@]HOST",
+                                   help="User and host of the QNetd server. 
The host can be specified in either hostname or IP address.")
         qdevice_group.add_argument("--qdevice-port", dest="qdevice_port", 
metavar="PORT", type=int, default=5403,
                                    help="TCP PORT of QNetd server 
(default:5403)")
         qdevice_group.add_argument("--qdevice-algo", dest="qdevice_algo", 
metavar="ALGORITHM", default="ffsplit", choices=['ffsplit', 'lms'],
@@ -413,7 +413,10 @@
         parser.add_argument("-w", "--watchdog", dest="watchdog", 
metavar="WATCHDOG", help="Use the given watchdog device")
 
         network_group = parser.add_argument_group("Network configuration", 
"Options for configuring the network and messaging layer.")
-        network_group.add_argument("-c", "--cluster-node", 
dest="cluster_node", help="IP address or hostname of existing cluster node", 
metavar="HOST")
+        network_group.add_argument(
+            "-c", "--cluster-node", dest="cluster_node", metavar="[USER@]HOST",
+            help="User and host to login to an existing cluster node. The host 
can be specified with either a hostname or an IP.",
+        )
         network_group.add_argument("-i", "--interface", dest="nic_list", 
metavar="IF", action="append", choices=utils.interface_choice(), default=[],
                 help="Bind to IP address on interface IF. Use -i second time 
for second interface")
         options, args = parse_options(parser, args)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/crmsh-4.5.0+20230424.75600b3f/crmsh/utils.py 
new/crmsh-4.5.0+20230427.11d11104/crmsh/utils.py
--- old/crmsh-4.5.0+20230424.75600b3f/crmsh/utils.py    2023-04-24 
10:59:23.000000000 +0200
+++ new/crmsh-4.5.0+20230427.11d11104/crmsh/utils.py    2023-04-27 
08:13:57.000000000 +0200
@@ -225,13 +225,19 @@
         raise ValueError('Can not create ssh session from {} to 
{}.'.format(this_node(), host))
 
 
-def ssh_copy_id(local_user, remote_user, remote_node):
+def ssh_copy_id_no_raise(local_user, remote_user, remote_node):
     if check_ssh_passwd_need(local_user, remote_user, remote_node):
         logger.info("Configuring SSH passwordless with 
{}@{}".format(remote_user, remote_node))
         cmd = "ssh-copy-id -i ~/.ssh/id_rsa.pub '{}@{}' &> 
/dev/null".format(remote_user, remote_node)
         result = su_subprocess_run(local_user, cmd, tty=True)
-        if result.returncode != 0:
-            fatal("Failed to login to remote host {}@{}".format(remote_user, 
remote_node))
+        return result.returncode
+    else:
+        return 0
+
+
+def ssh_copy_id(local_user, remote_user, remote_node):
+    if 0 != ssh_copy_id_no_raise(local_user, remote_user, remote_node):
+        fatal("Failed to login to remote host {}@{}".format(remote_user, 
remote_node))
 
 
 @memoize
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.5.0+20230424.75600b3f/test/features/bootstrap_bugs.feature 
new/crmsh-4.5.0+20230427.11d11104/test/features/bootstrap_bugs.feature
--- old/crmsh-4.5.0+20230424.75600b3f/test/features/bootstrap_bugs.feature      
2023-04-24 10:59:23.000000000 +0200
+++ new/crmsh-4.5.0+20230427.11d11104/test/features/bootstrap_bugs.feature      
2023-04-27 08:13:57.000000000 +0200
@@ -139,6 +139,18 @@
 
   @skip_non_root
   @clean
+  Scenario: crm cluster join default behavior change in ssh key handling 
(bsc#1210693)
+    Given   Cluster service is "stopped" on "hanode1"
+    Given   Cluster service is "stopped" on "hanode2"
+    When    Run "rm -rf /home/alice/.ssh" on "hanode1"
+    When    Run "rm -rf /home/alice/.ssh" on "hanode2"
+    When    Run "su - alice -c "sudo crm cluster init -y"" on "hanode1"
+    Then    Cluster service is "started" on "hanode1"
+    When    Run "su - alice -c "sudo crm cluster join -c hanode1 -y"" on 
"hanode2"
+    Then    Cluster service is "started" on "hanode2"
+
+  @skip_non_root
+  @clean
   Scenario: Passwordless for root, not for sudoer(bsc#1209193)
     Given   Cluster service is "stopped" on "hanode1"
     And     Cluster service is "stopped" on "hanode2"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.5.0+20230424.75600b3f/test/features/steps/const.py 
new/crmsh-4.5.0+20230427.11d11104/test/features/steps/const.py
--- old/crmsh-4.5.0+20230424.75600b3f/test/features/steps/const.py      
2023-04-24 10:59:23.000000000 +0200
+++ new/crmsh-4.5.0+20230427.11d11104/test/features/steps/const.py      
2023-04-27 08:13:57.000000000 +0200
@@ -107,8 +107,9 @@
   
   Options for configuring QDevice and QNetd.
 
-  --qnetd-hostname HOST
-                        HOST or IP of the QNetd server to be used
+  --qnetd-hostname [USER@]HOST
+                        User and host of the QNetd server. The host can be
+                        specified in either hostname or IP address.
   --qdevice-port PORT   TCP PORT of QNetd server (default:5403)
   --qdevice-algo ALGORITHM
                         QNetd decision ALGORITHM (ffsplit/lms,
@@ -223,8 +224,10 @@
 Network configuration:
   Options for configuring the network and messaging layer.
 
-  -c HOST, --cluster-node HOST
-                        IP address or hostname of existing cluster node
+  -c [USER@]HOST, --cluster-node [USER@]HOST
+                        User and host to login to an existing cluster node.
+                        The host can be specified with either a hostname or an
+                        IP.
   -i IF, --interface IF
                         Bind to IP address on interface IF. Use -i second time
                         for second interface
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.5.0+20230424.75600b3f/test/features/steps/utils.py 
new/crmsh-4.5.0+20230427.11d11104/test/features/steps/utils.py
--- old/crmsh-4.5.0+20230424.75600b3f/test/features/steps/utils.py      
2023-04-24 10:59:23.000000000 +0200
+++ new/crmsh-4.5.0+20230427.11d11104/test/features/steps/utils.py      
2023-04-27 08:13:57.000000000 +0200
@@ -4,7 +4,7 @@
 import glob
 import re
 import socket
-from crmsh import utils, bootstrap, parallax
+from crmsh import utils, bootstrap, parallax, userdir
 
 
 COLOR_MODE = r'\x1b\[[0-9]+m'
@@ -46,7 +46,28 @@
     return cmd
 
 
+def _wrap_cmd_non_root(cmd):
+    """
+    When running command under sudoer, or the current user is not root,
+    wrap crm cluster join command with '<user>@'
+    """
+    user = ""
+    sudoer = userdir.get_sudoer()
+    current_user = userdir.getuser()
+    if sudoer:
+        user = sudoer
+    elif current_user != 'root':
+        user = current_user
+    else:
+        return cmd
+    if "cluster join" in cmd and "@" not in cmd:
+        return re.sub("-c (\w+) ", f"-c {user}@\\1 ", cmd)
+    else:
+        return cmd
+
+
 def run_command(context, cmd, exit_on_fail=True):
+    cmd = _wrap_cmd_non_root(cmd)
     rc, out, err = utils.get_stdout_stderr(add_sudo(cmd))
     context.return_code = rc
     if out:
@@ -68,6 +89,7 @@
     if addr == me():
         return run_command(context, cmd, exit_on_fail)
     else:
+        cmd = _wrap_cmd_non_root(cmd)
         try:
             results = parallax.parallax_call(addr.split(','), cmd)
         except ValueError as err:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.5.0+20230424.75600b3f/test/unittests/test_bootstrap.py 
new/crmsh-4.5.0+20230427.11d11104/test/unittests/test_bootstrap.py
--- old/crmsh-4.5.0+20230424.75600b3f/test/unittests/test_bootstrap.py  
2023-04-24 10:59:23.000000000 +0200
+++ new/crmsh-4.5.0+20230427.11d11104/test/unittests/test_bootstrap.py  
2023-04-27 08:13:57.000000000 +0200
@@ -452,13 +452,14 @@
     @mock.patch('crmsh.bootstrap.change_user_shell')
     @mock.patch('crmsh.utils.su_get_stdout_or_raise_error')
     @mock.patch('crmsh.bootstrap.swap_public_ssh_key')
-    @mock.patch('crmsh.utils.ssh_copy_id')
+    @mock.patch('crmsh.utils.ssh_copy_id_no_raise')
     @mock.patch('crmsh.bootstrap.configure_ssh_key')
     @mock.patch('crmsh.utils.start_service')
     def test_join_ssh(self, mock_start_service, mock_config_ssh, 
mock_ssh_copy_id, mock_swap, mock_invoke, mock_change):
         bootstrap._context = mock.Mock(current_user="bob", 
user_list=["alice"], node_list=['node1'], default_nic_list=["eth1"])
         mock_invoke.return_value = ''
         mock_swap.return_value = None
+        mock_ssh_copy_id.return_value = 0
 
         bootstrap.join_ssh_impl("node1", "alice")
 
@@ -477,6 +478,30 @@
             "bob",
         )
 
+    @mock.patch('crmsh.bootstrap.change_user_shell')
+    @mock.patch('crmsh.utils.su_get_stdout_or_raise_error')
+    @mock.patch('crmsh.bootstrap.swap_public_ssh_key')
+    @mock.patch('crmsh.utils.ssh_copy_id_no_raise')
+    @mock.patch('crmsh.bootstrap.configure_ssh_key')
+    @mock.patch('crmsh.utils.start_service')
+    def test_join_ssh_bad_credential(self, mock_start_service, 
mock_config_ssh, mock_ssh_copy_id, mock_swap, mock_invoke, mock_change):
+        bootstrap._context = mock.Mock(current_user="bob", 
user_list=["alice"], node_list=['node1'], default_nic_list=["eth1"])
+        mock_invoke.return_value = ''
+        mock_swap.return_value = None
+        mock_ssh_copy_id.return_value = 255
+
+        with self.assertRaises(ValueError):
+            bootstrap.join_ssh_impl("node1", "alice")
+
+        mock_start_service.assert_called_once_with("sshd.service", enable=True)
+        mock_config_ssh.assert_has_calls([
+            mock.call("bob"),
+        ])
+        mock_ssh_copy_id.assert_called_once_with("bob", "alice", "node1")
+        mock_swap.assert_not_called()
+        mock_invoke.assert_not_called()
+
+
     @mock.patch('crmsh.bootstrap.import_ssh_key')
     @mock.patch('crmsh.bootstrap.export_ssh_key_non_interactive')
     @mock.patch('logging.Logger.warning')
@@ -801,7 +826,7 @@
     @mock.patch('crmsh.utils.HostUserConfig')
     @mock.patch('crmsh.utils.UserOfHost.instance')
     @mock.patch('crmsh.utils.list_cluster_nodes')
-    @mock.patch('crmsh.utils.ssh_copy_id')
+    @mock.patch('crmsh.utils.ssh_copy_id_no_raise')
     @mock.patch('crmsh.bootstrap.configure_ssh_key')
     @mock.patch('crmsh.utils.check_ssh_passwd_need')
     @mock.patch('logging.Logger.info')
@@ -814,7 +839,7 @@
         mock_list_nodes.return_value = []
         bootstrap._context = mock.Mock(qdevice_inst=self.qdevice_with_ip, 
current_user="bob", user_list=["alice"])
         mock_check_ssh_passwd_need.return_value = True
-        mock_ssh_copy_id.side_effect = ValueError('foo')
+        mock_ssh_copy_id.return_value = 255
         mock_user_of_host.return_value = mock.MagicMock(crmsh.utils.UserOfHost)
         mock_user_of_host.return_value.user_pair_for_ssh.return_value = "bob", 
"bob"
 

Reply via email to