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-03-22 22:31:48
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/crmsh (Old)
 and      /work/SRC/openSUSE:Factory/.crmsh.new.31432 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "crmsh"

Wed Mar 22 22:31:48 2023 rev:287 rq:1073807 version:4.5.0+20230321.97bd51bb

Changes:
--------
--- /work/SRC/openSUSE:Factory/crmsh/crmsh.changes      2023-03-21 
17:42:57.870242491 +0100
+++ /work/SRC/openSUSE:Factory/.crmsh.new.31432/crmsh.changes   2023-03-22 
22:32:36.478786759 +0100
@@ -1,0 +2,18 @@
+Tue Mar 21 15:30:12 UTC 2023 - xli...@suse.com
+
+- Update to version 4.5.0+20230321.97bd51bb:
+  * Dev: behave: Split the time cost case into two cases
+  * Dev: unittest: Adjust unit test for previous changes
+  * Dev: remove 'sudo' prefix internally
+
+-------------------------------------------------------------------
+Tue Mar 21 13:34:38 UTC 2023 - xli...@suse.com
+
+- Update to version 4.5.0+20230321.eda6d2d9:
+  * Dev: workflows: Disable resource_failcount.feature temporarily
+  * Dev: behave: Add test case for 'Passwordless for root, not for 
sudoer(bsc#1209193)'
+  * Dev: behave: check user shell after init and join, without upgrading
+  * Dev: bootstrap: Change user shell for hacluster on remote node, in 
init_ssh_impl function
+  * Dev: behave: Add functional test to check user shell for hacluster
+
+-------------------------------------------------------------------

Old:
----
  crmsh-4.5.0+20230320.5e777809.tar.bz2

New:
----
  crmsh-4.5.0+20230321.97bd51bb.tar.bz2

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

Other differences:
------------------
++++++ crmsh.spec ++++++
--- /var/tmp/diff_new_pack.aSrJAW/_old  2023-03-22 22:32:36.982789295 +0100
+++ /var/tmp/diff_new_pack.aSrJAW/_new  2023-03-22 22:32:36.986789315 +0100
@@ -36,7 +36,7 @@
 Summary:        High Availability cluster command-line interface
 License:        GPL-2.0-or-later
 Group:          %{pkg_group}
-Version:        4.5.0+20230320.5e777809
+Version:        4.5.0+20230321.97bd51bb
 Release:        0
 URL:            http://crmsh.github.io
 Source0:        %{name}-%{version}.tar.bz2

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.aSrJAW/_old  2023-03-22 22:32:37.030789536 +0100
+++ /var/tmp/diff_new_pack.aSrJAW/_new  2023-03-22 22:32:37.030789536 +0100
@@ -9,7 +9,7 @@
 </service>
 <service name="tar_scm">
   <param name="url">https://github.com/ClusterLabs/crmsh.git</param>
-  <param 
name="changesrevision">4697fb58457de1acf83640116e145612d97e593f</param>
+  <param 
name="changesrevision">e751cc863b8189ee541fd84a72bf1584d163ffcf</param>
 </service>
 </servicedata>
 (No newline at EOF)

++++++ crmsh-4.5.0+20230320.5e777809.tar.bz2 -> 
crmsh-4.5.0+20230321.97bd51bb.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.5.0+20230320.5e777809/.github/workflows/crmsh-ci.yml 
new/crmsh-4.5.0+20230321.97bd51bb/.github/workflows/crmsh-ci.yml
--- old/crmsh-4.5.0+20230320.5e777809/.github/workflows/crmsh-ci.yml    
2023-03-20 08:49:02.000000000 +0100
+++ new/crmsh-4.5.0+20230321.97bd51bb/.github/workflows/crmsh-ci.yml    
2023-03-21 16:02:58.000000000 +0100
@@ -74,7 +74,19 @@
         echo '{ "exec-opts": ["native.cgroupdriver=systemd"] }' | sudo tee 
/etc/docker/daemon.json
         sudo systemctl restart docker.service
         index=`$GET_INDEX_OF bootstrap_bugs`
-        $DOCKER_SCRIPT $index && $DOCKER_SCRIPT -d && $DOCKER_SCRIPT $index -u
+        $DOCKER_SCRIPT $index
+
+  functional_test_bootstrap_bugs_non_root:
+    runs-on: ubuntu-20.04
+    timeout-minutes: 40
+    steps:
+    - uses: actions/checkout@v3
+    - name: functional test for bootstrap bugs, under non root user
+      run:  |
+        echo '{ "exec-opts": ["native.cgroupdriver=systemd"] }' | sudo tee 
/etc/docker/daemon.json
+        sudo systemctl restart docker.service
+        index=`$GET_INDEX_OF bootstrap_bugs`
+        $DOCKER_SCRIPT $index -u
 
   functional_test_bootstrap_common:
     runs-on: ubuntu-20.04
@@ -86,7 +98,19 @@
         echo '{ "exec-opts": ["native.cgroupdriver=systemd"] }' | sudo tee 
/etc/docker/daemon.json
         sudo systemctl restart docker.service
         index=`$GET_INDEX_OF bootstrap_init_join_remove`
-        $DOCKER_SCRIPT $index && $DOCKER_SCRIPT -d && $DOCKER_SCRIPT $index -u
+        $DOCKER_SCRIPT $index
+
+  functional_test_bootstrap_common_non_root:
+    runs-on: ubuntu-20.04
+    timeout-minutes: 40
+    steps:
+    - uses: actions/checkout@v3
+    - name: functional test for bootstrap common, under non root user
+      run:  |
+        echo '{ "exec-opts": ["native.cgroupdriver=systemd"] }' | sudo tee 
/etc/docker/daemon.json
+        sudo systemctl restart docker.service
+        index=`$GET_INDEX_OF bootstrap_init_join_remove`
+        $DOCKER_SCRIPT $index -u
 
   functional_test_bootstrap_options:
     runs-on: ubuntu-20.04
@@ -110,7 +134,19 @@
         echo '{ "exec-opts": ["native.cgroupdriver=systemd"] }' | sudo tee 
/etc/docker/daemon.json
         sudo systemctl restart docker.service
         index=`$GET_INDEX_OF qdevice_setup_remove`
-        $DOCKER_SCRIPT $index && $DOCKER_SCRIPT -d && $DOCKER_SCRIPT $index -u
+        $DOCKER_SCRIPT $index
+
+  functional_test_qdevice_setup_remove_non_root:
+    runs-on: ubuntu-20.04
+    timeout-minutes: 40
+    steps:
+    - uses: actions/checkout@v3
+    - name: functional test for qdevice setup and remove, under non root user
+      run:  |
+        echo '{ "exec-opts": ["native.cgroupdriver=systemd"] }' | sudo tee 
/etc/docker/daemon.json
+        sudo systemctl restart docker.service
+        index=`$GET_INDEX_OF qdevice_setup_remove`
+        $DOCKER_SCRIPT $index -u
 
   functional_test_qdevice_options:
     runs-on: ubuntu-20.04
@@ -157,7 +193,7 @@
       run:  |
         echo '{ "exec-opts": ["native.cgroupdriver=systemd"] }' | sudo tee 
/etc/docker/daemon.json
         sudo systemctl restart docker.service
-        index=`$GET_INDEX_OF resource_failcount resource_set`
+        index=`$GET_INDEX_OF resource_set`
         $DOCKER_SCRIPT $index && $DOCKER_SCRIPT -d && $DOCKER_SCRIPT $index -u
 
   functional_test_configure_sublevel:
@@ -244,9 +280,12 @@
       unit_test,
       functional_test_crm_report_bugs,
       functional_test_bootstrap_bugs,
+      functional_test_bootstrap_bugs_non_root,
       functional_test_bootstrap_common,
+      functional_test_bootstrap_common_non_root,
       functional_test_bootstrap_options,
       functional_test_qdevice_setup_remove,
+      functional_test_qdevice_setup_remove_non_root,
       functional_test_qdevice_options,
       functional_test_qdevice_validate,
       functional_test_qdevice_user_case,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/crmsh-4.5.0+20230320.5e777809/crmsh/bootstrap.py 
new/crmsh-4.5.0+20230321.97bd51bb/crmsh/bootstrap.py
--- old/crmsh-4.5.0+20230320.5e777809/crmsh/bootstrap.py        2023-03-20 
08:49:02.000000000 +0100
+++ new/crmsh-4.5.0+20230321.97bd51bb/crmsh/bootstrap.py        2023-03-21 
16:02:58.000000000 +0100
@@ -695,7 +695,6 @@
     def init_firewall_firewalld(tcp, udp):
         has_firewalld = utils.service_is_active("firewalld")
         cmdbase = 'firewall-cmd --zone=public --permanent ' if has_firewalld 
else 'firewall-offline-cmd --zone=public '
-        cmdbase = 'sudo ' + cmdbase
 
         def cmd(args):
             if not invokerc(cmdbase + args):
@@ -708,7 +707,7 @@
             cmd("--add-port={}/udp".format(p))
 
         if has_firewalld:
-            if not invokerc("sudo firewall-cmd --reload"):
+            if not invokerc("firewall-cmd --reload"):
                 utils.fatal("Failed to reload firewall configuration.")
 
     def init_firewall_ufw(tcp, udp):
@@ -766,7 +765,7 @@
 
     # reset password, but only if it's not already set
     # (We still need the hacluster for the hawk).
-    _rc, outp = utils.get_stdout("sudo passwd -S hacluster")
+    _rc, outp = utils.get_stdout("passwd -S hacluster")
     ps = outp.strip().split()[1]
     pass_msg = ""
     if ps not in ("P", "PS"):
@@ -778,7 +777,7 @@
             pass_msg = ", password 'linux'"
 
     # evil, but necessary
-    invoke("sudo rm -f /var/lib/heartbeat/crm/* /var/lib/pacemaker/cib/*")
+    invoke("rm -f /var/lib/heartbeat/crm/* /var/lib/pacemaker/cib/*")
 
     # only try to start hawk if hawk is installed
     if utils.service_is_available("hawk.service"):
@@ -837,9 +836,10 @@
 
 
 def append(fromfile, tofile, remote=None):
-    cmd = "sudo bash -c 'cat {} >> {}'".format(fromfile, tofile)
+    cmd = "cat {} >> {}".format(fromfile, tofile)
     utils.get_stdout_or_raise_error(cmd, remote=remote)
 
+
 def append_unique(fromfile, tofile, user=None, remote=None, from_local=False):
     """
     Append unique content from fromfile to tofile
@@ -889,6 +889,7 @@
         # After this, login to remote_node is passwordless
         public_key_list.append(swap_public_ssh_key(node, local_user, 
remote_user, local_user, remote_user, add=True))
         hacluster_public_key_list.append(swap_public_ssh_key(node, 
'hacluster', 'hacluster', local_user, remote_user, add=True))
+        change_user_shell('hacluster', node)
     if len(node_list) > 1:
         shell_script = _merge_authorized_keys(public_key_list)
         hacluster_shell_script = 
_merge_authorized_keys(hacluster_public_key_list)
@@ -981,7 +982,7 @@
         return rc == 0
     else:
         with open(passwd_file) as f:
-            return re.search(pattern, f.read())
+            return re.search(pattern, f.read()) is not None
 
 
 def change_user_shell(user, remote=None):
@@ -1132,9 +1133,9 @@
         if not confirm("csync2 is already configured - overwrite?"):
             return
 
-    invoke("sudo rm", "-f", CSYNC2_KEY)
+    invoke("rm", "-f", CSYNC2_KEY)
     logger.debug("Generating csync2 shared key")
-    if not invokerc("sudo csync2", "-k", CSYNC2_KEY):
+    if not invokerc("csync2", "-k", CSYNC2_KEY):
         utils.fatal("Can't create csync2 key {}".format(CSYNC2_KEY))
 
     csync2_file_list = ""
@@ -1166,7 +1167,7 @@
         if _context.skip_csync2:
             csync2_update("/")
         else:
-            invoke("sudo csync2", "-cr", "/")
+            invoke("csync2", "-cr", "/")
 
 
 def csync2_update(path):
@@ -1175,11 +1176,11 @@
 
     If there was a conflict, use '-f' to force this side to win
     '''
-    invoke("sudo csync2 -rm {}".format(path))
-    if invokerc("sudo csync2 -rxv {}".format(path)):
+    invoke("csync2 -rm {}".format(path))
+    if invokerc("csync2 -rxv {}".format(path)):
         return
-    invoke("sudo csync2 -rf {}".format(path))
-    if not invokerc("sudo csync2 -rxv {}".format(path)):
+    invoke("csync2 -rf {}".format(path))
+    if not invokerc("csync2 -rxv {}".format(path)):
         logger.warning("{} was not synced".format(path))
 
 
@@ -1222,7 +1223,7 @@
         if not confirm("%s already exists - overwrite?" % (COROSYNC_AUTH)):
             return
         utils.rmfile(COROSYNC_AUTH)
-    invoke("sudo corosync-keygen -l -k {}".format(COROSYNC_AUTH))
+    invoke("corosync-keygen -l -k {}".format(COROSYNC_AUTH))
 
 
 def init_remote_auth():
@@ -1236,7 +1237,7 @@
 
     pcmk_remote_dir = os.path.dirname(PCMK_REMOTE_AUTH)
     utils.mkdirs_owned(pcmk_remote_dir, mode=0o750, gid="haclient")
-    if not invokerc("sudo dd if=/dev/urandom of={} bs=4096 
count=1".format(PCMK_REMOTE_AUTH)):
+    if not invokerc("dd if=/dev/urandom of={} bs=4096 
count=1".format(PCMK_REMOTE_AUTH)):
         logger.warning("Failed to create pacemaker authkey: 
{}".format(PCMK_REMOTE_AUTH))
     utils.chown(PCMK_REMOTE_AUTH, _context.current_user, "haclient")
     utils.chmod(PCMK_REMOTE_AUTH, 0o640)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/crmsh-4.5.0+20230320.5e777809/crmsh/sbd.py 
new/crmsh-4.5.0+20230321.97bd51bb/crmsh/sbd.py
--- old/crmsh-4.5.0+20230320.5e777809/crmsh/sbd.py      2023-03-20 
08:49:02.000000000 +0100
+++ new/crmsh-4.5.0+20230321.97bd51bb/crmsh/sbd.py      2023-03-21 
16:02:58.000000000 +0100
@@ -90,7 +90,7 @@
         """
         Get msgwait for sbd device
         """
-        out = utils.get_stdout_or_raise_error("sudo sbd -d {} 
dump".format(dev))
+        out = utils.get_stdout_or_raise_error("sbd -d {} dump".format(dev))
         # Format like "Timeout (msgwait)  : 30"
         res = re.search("\(msgwait\)\s+:\s+(\d+)", out)
         if not res:
@@ -292,7 +292,7 @@
         """
         Get UUID for specific device and node
         """
-        out = utils.get_stdout_or_raise_error("sudo sbd -d {} 
dump".format(dev), remote=node)
+        out = utils.get_stdout_or_raise_error("sbd -d {} dump".format(dev), 
remote=node)
         res = re.search("UUID\s*:\s*(.*)\n", out)
         if not res:
             raise ValueError("Cannot find sbd device UUID for {}".format(dev))
@@ -419,7 +419,7 @@
         for dev in self._sbd_devices:
             if dev in self.no_overwrite_map and self.no_overwrite_map[dev]:
                 continue
-            rc, _, err = bootstrap.invoke("sudo sbd {} -d {} 
create".format(opt, dev))
+            rc, _, err = bootstrap.invoke("sbd {} -d {} create".format(opt, 
dev))
             if not rc:
                 utils.fatal("Failed to initialize SBD device {}: 
{}".format(dev, err))
 
@@ -478,7 +478,7 @@
             self._restart_cluster_and_configure_sbd_ra()
         else:
             # in init process
-            bootstrap.invoke("sudo systemctl enable sbd.service")
+            bootstrap.invoke("systemctl enable sbd.service")
 
     def _warn_diskless_sbd(self, peer=None):
         """
@@ -509,7 +509,7 @@
         self._watchdog_inst.init_watchdog()
         self._get_sbd_device()
         if not self._sbd_devices and not self.diskless_sbd:
-            bootstrap.invoke("sudo systemctl disable sbd.service")
+            bootstrap.invoke("systemctl disable sbd.service")
             return
         self._warn_diskless_sbd()
         self._initialize_sbd()
@@ -552,7 +552,7 @@
         if not utils.package_is_installed("sbd"):
             return
         if not os.path.exists(SYSCONFIG_SBD) or not 
utils.service_is_enabled("sbd.service", peer_host):
-            bootstrap.invoke("sudo systemctl disable sbd.service")
+            bootstrap.invoke("systemctl disable sbd.service")
             return
         self._watchdog_inst = Watchdog(remote_user=remote_user, 
peer_host=peer_host)
         self._watchdog_inst.join_watchdog()
@@ -562,7 +562,7 @@
         else:
             self._warn_diskless_sbd(peer_host)
         logger.info("Got {}SBD configuration".format("" if dev_list else 
"diskless "))
-        bootstrap.invoke("sudo systemctl enable sbd.service")
+        bootstrap.invoke("systemctl enable sbd.service")
 
     @classmethod
     def verify_sbd_device(cls):
@@ -617,6 +617,6 @@
         """
         Check if sbd device already initialized
         """
-        cmd = "sudo sbd -d {} dump".format(dev)
+        cmd = "sbd -d {} dump".format(dev)
         rc, _, _ = utils.get_stdout_stderr(cmd)
         return rc == 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/crmsh-4.5.0+20230320.5e777809/crmsh/utils.py 
new/crmsh-4.5.0+20230321.97bd51bb/crmsh/utils.py
--- old/crmsh-4.5.0+20230320.5e777809/crmsh/utils.py    2023-03-20 
08:49:02.000000000 +0100
+++ new/crmsh-4.5.0+20230321.97bd51bb/crmsh/utils.py    2023-03-21 
16:02:58.000000000 +0100
@@ -2253,9 +2253,9 @@
     Detect if in AWS
     """
     # will match on xen instances
-    xen_test = get_stdout_or_raise_error("sudo dmidecode -s 
system-version").lower()
+    xen_test = get_stdout_or_raise_error("dmidecode -s system-version").lower()
     # will match on nitro/kvm instances
-    kvm_test = get_stdout_or_raise_error("sudo dmidecode -s 
system-manufacturer").lower()
+    kvm_test = get_stdout_or_raise_error("dmidecode -s 
system-manufacturer").lower()
     if "amazon" in xen_test or "amazon" in kvm_test:
         return True
     return False
@@ -2270,8 +2270,8 @@
     # might return American Megatrends Inc. instead of Microsoft Corporation 
in Azure.
     # The better way is to check the result of dmidecode -s chassis-asset-tag 
is
     # 7783-7084-3265-9085-8269-3286-77, aka. the ascii code of MSFT AZURE VM
-    system_manufacturer = get_stdout_or_raise_error("sudo dmidecode -s 
system-manufacturer")
-    chassis_asset_tag = get_stdout_or_raise_error("sudo dmidecode -s 
chassis-asset-tag")
+    system_manufacturer = get_stdout_or_raise_error("dmidecode -s 
system-manufacturer")
+    chassis_asset_tag = get_stdout_or_raise_error("dmidecode -s 
chassis-asset-tag")
     if "microsoft corporation" in system_manufacturer.lower() or \
             ''.join([chr(int(n)) for n in re.findall("\d\d", 
chassis_asset_tag)]) == "MSFT AZURE VM":
         # To detect azure we also need to make an API request
@@ -2287,7 +2287,7 @@
     """
     Detect if in GCP
     """
-    bios_vendor = get_stdout_or_raise_error("sudo dmidecode -s bios-vendor")
+    bios_vendor = get_stdout_or_raise_error("dmidecode -s bios-vendor")
     if "Google" in bios_vendor:
         # To detect GCP we also need to make an API request
         result = _cloud_metadata_request(
@@ -2742,9 +2742,9 @@
     if not detect_file(target_file, remote=remote):
         return False
 
-    cmd = "sudo cat {}".format(target_file)
+    cmd = "cat {}".format(target_file)
     target_data = get_stdout_or_raise_error(cmd, remote=remote)
-    cmd = "sudo cat {}".format(source_file)
+    cmd = "cat {}".format(source_file)
     source_data = get_stdout_or_raise_error(cmd, remote=None if source_local 
else remote)
     return source_data in target_data
 
@@ -3423,7 +3423,7 @@
     """
     rc = False
     if not remote:
-        cmd = "sudo test -f {}".format(_file)
+        cmd = "test -f {}".format(_file)
     else:
         # FIXME
         cmd = "ssh {} {}@{} 'test -f {}'".format(SSH_OPTION, user_of(remote), 
remote, _file)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/crmsh-4.5.0+20230320.5e777809/crmsh/watchdog.py 
new/crmsh-4.5.0+20230321.97bd51bb/crmsh/watchdog.py
--- old/crmsh-4.5.0+20230320.5e777809/crmsh/watchdog.py 2023-03-20 
08:49:02.000000000 +0100
+++ new/crmsh-4.5.0+20230321.97bd51bb/crmsh/watchdog.py 2023-03-21 
16:02:58.000000000 +0100
@@ -30,7 +30,7 @@
         """
         Use wdctl to verify watchdog device
         """
-        rc, _, err = utils.get_stdout_stderr("sudo wdctl {}".format(dev))
+        rc, _, err = utils.get_stdout_stderr("wdctl {}".format(dev))
         if rc != 0:
             if ignore_error:
                 return False
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.5.0+20230320.5e777809/test/features/bootstrap_bugs.feature 
new/crmsh-4.5.0+20230321.97bd51bb/test/features/bootstrap_bugs.feature
--- old/crmsh-4.5.0+20230320.5e777809/test/features/bootstrap_bugs.feature      
2023-03-20 08:49:02.000000000 +0100
+++ new/crmsh-4.5.0+20230321.97bd51bb/test/features/bootstrap_bugs.feature      
2023-03-21 16:02:58.000000000 +0100
@@ -136,3 +136,22 @@
     Then    Service "corosync" is "started" on "hanode1"
     When    Run "crm cluster stop" on "hanode1"
     Then    Service "corosync" is "stopped" on "hanode1"
+
+  @clean
+  @skip_non_root
+  Scenario: Passwordless for root, not for sudoer(bsc#1209193)
+    Given   Cluster service is "stopped" on "hanode1"
+    And     Cluster service is "stopped" on "hanode2"
+    When    Run "crm cluster init -y" on "hanode1"
+    Then    Cluster service is "started" on "hanode1"
+    When    Run "crm cluster join -c hanode1 -y" on "hanode2"
+    Then    Cluster service is "started" on "hanode2"
+    When    Run "useradd -m -s /bin/bash xin" on "hanode1"
+    When    Run "echo "xin ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/xin" on 
"hanode1"
+    When    Run "rm -f /root/.config/crm/crm.conf" on "hanode1"
+    When    Run "useradd -m -s /bin/bash xin" on "hanode2"
+    When    Run "echo "xin ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/xin" on 
"hanode2"
+    When    Run "rm -f /root/.config/crm/crm.conf" on "hanode2"
+    When    Run "su xin -c "sudo crm cluster run 'touch /tmp/1209193'"" on 
"hanode1"
+    And     Run "test -f /tmp/1209193" on "hanode1"
+    And     Run "test -f /tmp/1209193" on "hanode2"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.5.0+20230320.5e777809/test/features/bootstrap_init_join_remove.feature
 
new/crmsh-4.5.0+20230321.97bd51bb/test/features/bootstrap_init_join_remove.feature
--- 
old/crmsh-4.5.0+20230320.5e777809/test/features/bootstrap_init_join_remove.feature
  2023-03-20 08:49:02.000000000 +0100
+++ 
new/crmsh-4.5.0+20230321.97bd51bb/test/features/bootstrap_init_join_remove.feature
  2023-03-21 16:02:58.000000000 +0100
@@ -152,6 +152,7 @@
     Then    Directory "/var/lib/corosync/" is empty on "hanode1"
 
   Scenario: Check hacluster's passwordless configuration on 2 nodes
+    Then    Check user shell for hacluster between "hanode1 hanode2"
     Then    Check passwordless for hacluster between "hanode1 hanode2"
 
   Scenario: Check hacluster's passwordless configuration in old cluster, 2 
nodes
@@ -171,6 +172,7 @@
     When    Run "crm cluster join -c hanode1 -y" on "hanode3"
     Then    Cluster service is "started" on "hanode3"
     And     Online nodes are "hanode1 hanode2 hanode3"
+    And     Check user shell for hacluster between "hanode1 hanode2 hanode3"
     And     Check passwordless for hacluster between "hanode1 hanode2 hanode3"
 
   Scenario: Check hacluster's passwordless configuration in old cluster, 3 
nodes
@@ -181,3 +183,21 @@
     Then    Cluster service is "started" on "hanode3"
     And     Online nodes are "hanode1 hanode2 hanode3"
     And     Check passwordless for hacluster between "hanode1 hanode2 hanode3"
+
+  Scenario: Check hacluster's user shell
+    Given   Cluster service is "stopped" on "hanode3"
+    When    Run "crm cluster join -c hanode1 -y" on "hanode3"
+    Then    Cluster service is "started" on "hanode3"
+    And     Online nodes are "hanode1 hanode2 hanode3"
+    When    Run "rm -rf /var/lib/heartbeat/cores/hacluster/.ssh" on "hanode1"
+    And     Run "rm -rf /var/lib/heartbeat/cores/hacluster/.ssh" on "hanode2"
+    And     Run "rm -rf /var/lib/heartbeat/cores/hacluster/.ssh" on "hanode3"
+    And     Run "usermod -s /usr/sbin/nologin hacluster" on "hanode1"
+    And     Run "usermod -s /usr/sbin/nologin hacluster" on "hanode2"
+    And     Run "usermod -s /usr/sbin/nologin hacluster" on "hanode3"
+    And     Run "rm -f /var/lib/crmsh/upgrade_seq" on "hanode1"
+    And     Run "rm -f /var/lib/crmsh/upgrade_seq" on "hanode2"
+    And     Run "rm -f /var/lib/crmsh/upgrade_seq" on "hanode3"
+    And     Run "crm status" on "hanode1"
+    Then    Check user shell for hacluster between "hanode1 hanode2 hanode3"
+    Then    Check passwordless for hacluster between "hanode1 hanode2 hanode3"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.5.0+20230320.5e777809/test/features/environment.py 
new/crmsh-4.5.0+20230321.97bd51bb/test/features/environment.py
--- old/crmsh-4.5.0+20230320.5e777809/test/features/environment.py      
2023-03-20 08:49:02.000000000 +0100
+++ new/crmsh-4.5.0+20230321.97bd51bb/test/features/environment.py      
2023-03-21 16:02:58.000000000 +0100
@@ -1,6 +1,6 @@
 import logging
 import re
-from crmsh import utils, parallax
+from crmsh import utils, parallax, userdir
 import time
 
 
@@ -32,3 +32,7 @@
                 if utils.get_dc():
                     break
             utils.get_stdout_or_raise_error("sudo crm cluster stop --all")
+    if tag == "skip_non_root":
+        sudoer = userdir.get_sudoer()
+        if sudoer or userdir.getuser() != 'root':
+            context.scenario.skip()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.5.0+20230320.5e777809/test/features/steps/step_implementation.py 
new/crmsh-4.5.0+20230321.97bd51bb/test/features/steps/step_implementation.py
--- 
old/crmsh-4.5.0+20230320.5e777809/test/features/steps/step_implementation.py    
    2023-03-20 08:49:02.000000000 +0100
+++ 
new/crmsh-4.5.0+20230321.97bd51bb/test/features/steps/step_implementation.py    
    2023-03-21 16:02:58.000000000 +0100
@@ -6,7 +6,7 @@
 
 import behave
 from behave import given, when, then
-from crmsh import corosync, parallax, sbd, userdir
+from crmsh import corosync, parallax, sbd, userdir, bootstrap
 from crmsh import utils as crmutils
 from utils import check_cluster_state, check_service_state, online, 
run_command, me, \
                   run_command_local_or_remote, file_in_archive, \
@@ -494,3 +494,13 @@
                 cmd = f"ssh {node} \"{cmd}\""
             context.logger.info(f"\nRun cmd: {cmd}")
             run_command(context, cmd)
+
+@then('Check user shell for hacluster between "{nodelist}"')
+def step_impl(context, nodelist):
+    if userdir.getuser() != 'root' or userdir.get_sudoer():
+        return True
+    for node in nodelist.split():
+        if node == me():
+            assert bootstrap.is_nologin('hacluster') is False
+        else:
+            assert bootstrap.is_nologin('hacluster', node) is False
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.5.0+20230320.5e777809/test/unittests/test_bootstrap.py 
new/crmsh-4.5.0+20230321.97bd51bb/test/unittests/test_bootstrap.py
--- old/crmsh-4.5.0+20230320.5e777809/test/unittests/test_bootstrap.py  
2023-03-20 08:49:02.000000000 +0100
+++ new/crmsh-4.5.0+20230321.97bd51bb/test/unittests/test_bootstrap.py  
2023-03-21 16:02:58.000000000 +0100
@@ -756,8 +756,8 @@
     def test_csync2_update_no_conflicts(self, mock_invoke, mock_invokerc):
         mock_invokerc.return_value = True
         bootstrap.csync2_update("/etc/corosync.conf")
-        mock_invoke.assert_called_once_with("sudo csync2 -rm 
/etc/corosync.conf")
-        mock_invokerc.assert_called_once_with("sudo csync2 -rxv 
/etc/corosync.conf")
+        mock_invoke.assert_called_once_with("csync2 -rm /etc/corosync.conf")
+        mock_invokerc.assert_called_once_with("csync2 -rxv /etc/corosync.conf")
 
     @mock.patch('logging.Logger.warning')
     @mock.patch('crmsh.bootstrap.invokerc')
@@ -766,12 +766,12 @@
         mock_invokerc.side_effect = [False, False]
         bootstrap.csync2_update("/etc/corosync.conf")
         mock_invoke.assert_has_calls([
-            mock.call("sudo csync2 -rm /etc/corosync.conf"),
-            mock.call("sudo csync2 -rf /etc/corosync.conf")
+            mock.call("csync2 -rm /etc/corosync.conf"),
+            mock.call("csync2 -rf /etc/corosync.conf")
             ])
         mock_invokerc.assert_has_calls([
-            mock.call("sudo csync2 -rxv /etc/corosync.conf"),
-            mock.call("sudo csync2 -rxv /etc/corosync.conf")
+            mock.call("csync2 -rxv /etc/corosync.conf"),
+            mock.call("csync2 -rxv /etc/corosync.conf")
             ])
         mock_warn.assert_called_once_with("/etc/corosync.conf was not synced")
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.5.0+20230320.5e777809/test/unittests/test_sbd.py 
new/crmsh-4.5.0+20230321.97bd51bb/test/unittests/test_sbd.py
--- old/crmsh-4.5.0+20230320.5e777809/test/unittests/test_sbd.py        
2023-03-20 08:49:02.000000000 +0100
+++ new/crmsh-4.5.0+20230321.97bd51bb/test/unittests/test_sbd.py        
2023-03-21 16:02:58.000000000 +0100
@@ -87,7 +87,7 @@
         with self.assertRaises(ValueError) as err:
             sbd.SBDTimeout.get_sbd_msgwait("/dev/sda1")
         self.assertEqual("Cannot get sbd msgwait for /dev/sda1", 
str(err.exception))
-        mock_run.assert_called_once_with("sudo sbd -d /dev/sda1 dump")
+        mock_run.assert_called_once_with("sbd -d /dev/sda1 dump")
 
     @mock.patch('crmsh.utils.get_stdout_or_raise_error')
     def test_get_sbd_msgwait(self, mock_run):
@@ -98,7 +98,7 @@
         """
         res = sbd.SBDTimeout.get_sbd_msgwait("/dev/sda1")
         assert res == 10
-        mock_run.assert_called_once_with("sudo sbd -d /dev/sda1 dump")
+        mock_run.assert_called_once_with("sbd -d /dev/sda1 dump")
 
     @mock.patch('crmsh.sbd.SBDManager.get_sbd_value_from_config')
     def test_get_sbd_watchdog_timeout_exception(self, mock_get):
@@ -500,8 +500,8 @@
             self.sbd_inst._initialize_sbd()
 
         mock_invoke.assert_has_calls([
-            mock.call("sudo sbd -4 10 -1 5 -d /dev/sdb1 create"),
-            mock.call("sudo sbd -4 10 -1 5 -d /dev/sdc1 create")
+            mock.call("sbd -4 10 -1 5 -d /dev/sdb1 create"),
+            mock.call("sbd -4 10 -1 5 -d /dev/sdc1 create")
             ])
         mock_error.assert_called_once_with("Failed to initialize SBD device 
/dev/sdc1: error")
 
@@ -591,7 +591,7 @@
         mock_update.assert_not_called()
         mock_watchdog.assert_called_once_with(_input=None)
         mock_watchdog_inst.init_watchdog.assert_called_once_with()
-        mock_invoke.assert_called_once_with("sudo systemctl disable 
sbd.service")
+        mock_invoke.assert_called_once_with("systemctl disable sbd.service")
  
     @mock.patch('crmsh.sbd.SBDManager._enable_sbd_service')
     @mock.patch('crmsh.sbd.SBDManager._warn_diskless_sbd')
@@ -658,7 +658,7 @@
     def test_enable_sbd_service_init(self, mock_invoke):
         self.sbd_inst._context = mock.Mock(cluster_is_running=False)
         self.sbd_inst._enable_sbd_service()
-        mock_invoke.assert_called_once_with("sudo systemctl enable 
sbd.service")
+        mock_invoke.assert_called_once_with("systemctl enable sbd.service")
 
     @mock.patch('crmsh.sbd.SBDManager._restart_cluster_and_configure_sbd_ra')
     @mock.patch('crmsh.utils.cluster_run_cmd')
@@ -713,7 +713,7 @@
         self.sbd_inst.join_sbd("alice", "node1")
         mock_package.assert_called_once_with("sbd")
         mock_exists.assert_called_once_with("/etc/sysconfig/sbd")
-        mock_invoke.assert_called_once_with("sudo systemctl disable 
sbd.service")
+        mock_invoke.assert_called_once_with("systemctl disable sbd.service")
 
     @mock.patch('crmsh.bootstrap.invoke')
     @mock.patch('crmsh.utils.service_is_enabled')
@@ -728,7 +728,7 @@
 
         mock_package.assert_called_once_with("sbd")
         mock_exists.assert_called_once_with("/etc/sysconfig/sbd")
-        mock_invoke.assert_called_once_with("sudo systemctl disable 
sbd.service")
+        mock_invoke.assert_called_once_with("systemctl disable sbd.service")
         mock_enabled.assert_called_once_with("sbd.service", "node1")
 
     @mock.patch('logging.Logger.info')
@@ -752,7 +752,7 @@
 
         mock_package.assert_called_once_with("sbd")
         mock_exists.assert_called_once_with("/etc/sysconfig/sbd")
-        mock_invoke.assert_called_once_with("sudo systemctl enable 
sbd.service")
+        mock_invoke.assert_called_once_with("systemctl enable sbd.service")
         mock_get_device.assert_called_once_with()
         mock_verify.assert_called_once_with(["/dev/sdb1"], ["node1"])
         mock_enabled.assert_called_once_with("sbd.service", "node1")
@@ -782,7 +782,7 @@
 
         mock_package.assert_called_once_with("sbd")
         mock_exists.assert_called_once_with("/etc/sysconfig/sbd")
-        mock_invoke.assert_called_once_with("sudo systemctl enable 
sbd.service")
+        mock_invoke.assert_called_once_with("systemctl enable sbd.service")
         mock_get_device.assert_called_once_with()
         mock_warn.assert_called_once_with("node1")
         mock_enabled.assert_called_once_with("sbd.service", "node1")
@@ -827,7 +827,7 @@
         with self.assertRaises(ValueError) as err:
             self.sbd_inst._get_device_uuid("/dev/sdb1")
         self.assertEqual("Cannot find sbd device UUID for /dev/sdb1", 
str(err.exception))
-        mock_run.assert_called_once_with("sudo sbd -d /dev/sdb1 dump", 
remote=None)
+        mock_run.assert_called_once_with("sbd -d /dev/sdb1 dump", remote=None)
 
     @mock.patch('crmsh.utils.get_stdout_or_raise_error')
     def test_get_device_uuid(self, mock_run):
@@ -846,7 +846,7 @@
         mock_run.return_value = output
         res = self.sbd_inst._get_device_uuid("/dev/sda1", node="node1")
         self.assertEqual(res, "a2e9a92c-cc72-4ef9-ac55-ccc342f3546b")
-        mock_run.assert_called_once_with("sudo sbd -d /dev/sda1 dump", 
remote="node1")
+        mock_run.assert_called_once_with("sbd -d /dev/sda1 dump", 
remote="node1")
 
     @mock.patch('crmsh.sbd.SBDManager._get_sbd_device_from_config')
     @mock.patch('crmsh.utils.service_is_active')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.5.0+20230320.5e777809/test/unittests/test_utils.py 
new/crmsh-4.5.0+20230321.97bd51bb/test/unittests/test_utils.py
--- old/crmsh-4.5.0+20230320.5e777809/test/unittests/test_utils.py      
2023-03-20 08:49:02.000000000 +0100
+++ new/crmsh-4.5.0+20230321.97bd51bb/test/unittests/test_utils.py      
2023-03-21 16:02:58.000000000 +0100
@@ -67,8 +67,8 @@
         mock.call("file2", remote=None)
         ])
     mock_run.assert_has_calls([
-        mock.call("sudo cat file2", remote=None),
-        mock.call("sudo cat file1", remote=None)
+        mock.call("cat file2", remote=None),
+        mock.call("cat file1", remote=None)
         ])
 
 
@@ -491,8 +491,8 @@
     mock_run.side_effect = ["test", "test"]
     assert utils.detect_aws() is False
     mock_run.assert_has_calls([
-        mock.call("sudo dmidecode -s system-version"),
-        mock.call("sudo dmidecode -s system-manufacturer")
+        mock.call("dmidecode -s system-version"),
+        mock.call("dmidecode -s system-manufacturer")
         ])
 
 @mock.patch("crmsh.utils.get_stdout_or_raise_error")
@@ -500,8 +500,8 @@
     mock_run.side_effect = ["4.2.amazon", "Xen"]
     assert utils.detect_aws() is True
     mock_run.assert_has_calls([
-        mock.call("sudo dmidecode -s system-version"),
-        mock.call("sudo dmidecode -s system-manufacturer")
+        mock.call("dmidecode -s system-version"),
+        mock.call("dmidecode -s system-manufacturer")
         ])
 
 @mock.patch("crmsh.utils.get_stdout_or_raise_error")
@@ -509,8 +509,8 @@
     mock_run.side_effect = ["Not Specified", "Amazon EC2"]
     assert utils.detect_aws() is True
     mock_run.assert_has_calls([
-        mock.call("sudo dmidecode -s system-version"),
-        mock.call("sudo dmidecode -s system-manufacturer")
+        mock.call("dmidecode -s system-version"),
+        mock.call("dmidecode -s system-manufacturer")
         ])
 
 @mock.patch("crmsh.utils.get_stdout_or_raise_error")
@@ -518,8 +518,8 @@
     mock_run.side_effect = ["test", "test"]
     assert utils.detect_azure() is False
     mock_run.assert_has_calls([
-        mock.call("sudo dmidecode -s system-manufacturer"),
-        mock.call("sudo dmidecode -s chassis-asset-tag")
+        mock.call("dmidecode -s system-manufacturer"),
+        mock.call("dmidecode -s chassis-asset-tag")
         ])
 
 @mock.patch("crmsh.utils._cloud_metadata_request")
@@ -529,8 +529,8 @@
     mock_request.return_value = "data"
     assert utils.detect_azure() is True
     mock_run.assert_has_calls([
-        mock.call("sudo dmidecode -s system-manufacturer"),
-        mock.call("sudo dmidecode -s chassis-asset-tag")
+        mock.call("dmidecode -s system-manufacturer"),
+        mock.call("dmidecode -s chassis-asset-tag")
         ])
 
 @mock.patch("crmsh.utils._cloud_metadata_request")
@@ -540,15 +540,15 @@
     mock_request.return_value = "data"
     assert utils.detect_azure() is True
     mock_run.assert_has_calls([
-        mock.call("sudo dmidecode -s system-manufacturer"),
-        mock.call("sudo dmidecode -s chassis-asset-tag")
+        mock.call("dmidecode -s system-manufacturer"),
+        mock.call("dmidecode -s chassis-asset-tag")
         ])
 
 @mock.patch("crmsh.utils.get_stdout_or_raise_error")
 def test_detect_gcp_false(mock_run):
     mock_run.return_value = "test"
     assert utils.detect_gcp() is False
-    mock_run.assert_called_once_with("sudo dmidecode -s bios-vendor")
+    mock_run.assert_called_once_with("dmidecode -s bios-vendor")
 
 @mock.patch("crmsh.utils._cloud_metadata_request")
 @mock.patch("crmsh.utils.get_stdout_or_raise_error")
@@ -556,7 +556,7 @@
     mock_run.return_value = "Google instance"
     mock_request.return_value = "data"
     assert utils.detect_gcp() is True
-    mock_run.assert_called_once_with("sudo dmidecode -s bios-vendor")
+    mock_run.assert_called_once_with("dmidecode -s bios-vendor")
 
 @mock.patch("crmsh.utils.is_program")
 def test_detect_cloud_no_cmd(mock_is_program):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.5.0+20230320.5e777809/test/unittests/test_watchdog.py 
new/crmsh-4.5.0+20230321.97bd51bb/test/unittests/test_watchdog.py
--- old/crmsh-4.5.0+20230320.5e777809/test/unittests/test_watchdog.py   
2023-03-20 08:49:02.000000000 +0100
+++ new/crmsh-4.5.0+20230321.97bd51bb/test/unittests/test_watchdog.py   
2023-03-21 16:02:58.000000000 +0100
@@ -48,7 +48,7 @@
         mock_run.return_value = (1, None, "error")
         res = self.watchdog_inst._verify_watchdog_device("/dev/watchdog", True)
         self.assertEqual(res, False)
-        mock_run.assert_called_once_with("sudo wdctl /dev/watchdog")
+        mock_run.assert_called_once_with("wdctl /dev/watchdog")
 
     @mock.patch('crmsh.utils.fatal')
     @mock.patch('crmsh.utils.get_stdout_stderr')
@@ -58,7 +58,7 @@
         with self.assertRaises(ValueError) as err:
             self.watchdog_inst._verify_watchdog_device("/dev/watchdog")
         mock_error.assert_called_once_with("Invalid watchdog device 
/dev/watchdog: error")
-        mock_run.assert_called_once_with("sudo wdctl /dev/watchdog")
+        mock_run.assert_called_once_with("wdctl /dev/watchdog")
 
     @mock.patch('crmsh.utils.get_stdout_stderr')
     def test_verify_watchdog_device(self, mock_run):

Reply via email to