Hello community,

here is the log from the commit of package crmsh for openSUSE:Factory checked 
in at 2020-02-18 13:29:25
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/crmsh (Old)
 and      /work/SRC/openSUSE:Factory/.crmsh.new.26092 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "crmsh"

Tue Feb 18 13:29:25 2020 rev:174 rq:775026 version:4.2.0+git.1581993539.5a1deb03

Changes:
--------
--- /work/SRC/openSUSE:Factory/crmsh/crmsh.changes      2020-02-03 
11:16:24.629938705 +0100
+++ /work/SRC/openSUSE:Factory/.crmsh.new.26092/crmsh.changes   2020-02-18 
13:29:26.480706709 +0100
@@ -1,0 +2,10 @@
+Tue Feb 18 02:53:29 UTC 2020 - xli...@suse.com
+
+- Update to version 4.2.0+git.1581993539.5a1deb03:
+  * Dev: behave: functional test for setup cluster with crossed network
+  * Dev: unittest: test for get_peer_hostname/is_online/find_configured_ip 
functions
+  * Dev: corosync: check whether local ip has already configured
+  * Dev: bootstrap: check whether init node is online while joining
+  * Dev: bootstrap: for udpu, don't check join node's ip was in the same 
network
+
+-------------------------------------------------------------------

Old:
----
  crmsh-4.2.0+git.1580544897.c42c9530.tar.bz2

New:
----
  crmsh-4.2.0+git.1581993539.5a1deb03.tar.bz2

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

Other differences:
------------------
++++++ crmsh.spec ++++++
--- /var/tmp/diff_new_pack.2egUa9/_old  2020-02-18 13:29:27.540708771 +0100
+++ /var/tmp/diff_new_pack.2egUa9/_new  2020-02-18 13:29:27.548708786 +0100
@@ -36,7 +36,7 @@
 Summary:        High Availability cluster command-line interface
 License:        GPL-2.0-or-later
 Group:          %{pkg_group}
-Version:        4.2.0+git.1580544897.c42c9530
+Version:        4.2.0+git.1581993539.5a1deb03
 Release:        0
 Url:            http://crmsh.github.io
 Source0:        %{name}-%{version}.tar.bz2

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.2egUa9/_old  2020-02-18 13:29:27.608708902 +0100
+++ /var/tmp/diff_new_pack.2egUa9/_new  2020-02-18 13:29:27.608708902 +0100
@@ -5,4 +5,4 @@
                 <param 
name="url">https://github.com/liangxin1300/crmsh.git</param>
               <param 
name="changesrevision">d8dc51b4cb34964aa72e918999ebc7f03b48f3c9</param></service><service
 name="tar_scm">
                 <param 
name="url">https://github.com/ClusterLabs/crmsh.git</param>
-              <param 
name="changesrevision">a8fc76646a14dfcf7b34e62303d2195ef96c3daa</param></service></servicedata>
\ No newline at end of file
+              <param 
name="changesrevision">e2a36e8724bbbb63a85806255adc08396883b53a</param></service></servicedata>
\ No newline at end of file

++++++ crmsh-4.2.0+git.1580544897.c42c9530.tar.bz2 -> 
crmsh-4.2.0+git.1581993539.5a1deb03.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.2.0+git.1580544897.c42c9530/crmsh/bootstrap.py 
new/crmsh-4.2.0+git.1581993539.5a1deb03/crmsh/bootstrap.py
--- old/crmsh-4.2.0+git.1580544897.c42c9530/crmsh/bootstrap.py  2020-02-01 
09:14:57.000000000 +0100
+++ new/crmsh-4.2.0+git.1581993539.5a1deb03/crmsh/bootstrap.py  2020-02-18 
03:38:59.000000000 +0100
@@ -18,6 +18,7 @@
 import re
 import time
 import readline
+import shutil
 from string import Template
 from lxml import etree
 from . import config
@@ -38,6 +39,7 @@
 SYSCONFIG_FW = "/etc/sysconfig/SuSEfirewall2"
 SYSCONFIG_FW_CLUSTER = "/etc/sysconfig/SuSEfirewall2.d/services/cluster"
 PCMK_REMOTE_AUTH = "/etc/pacemaker/authkey"
+COROSYNC_CONF_ORIG = tmpfiles.create()[1]
 
 
 INIT_STAGES = ("ssh", "ssh_remote", "csync2", "csync2_remote", "corosync", 
"storage", "sbd", "cluster", "vgfs", "admin", "qdevice")
@@ -228,13 +230,53 @@
     status_long("Waiting for cluster")
     while True:
         _rc, out, _err = utils.get_stdout_stderr("crm_mon -1")
-        if "online" in out.lower():
+        if is_online(out):
             break
         status_progress()
-        sleep(5)
+        sleep(2)
     status_done()
 
 
+def get_cluster_node_hostname():
+    """
+    Get the hostname of the cluster node used during the join process if an IP 
address is used.
+    """
+    peer_node = None
+    if _context.cluster_node:
+        if utils.valid_ip_addr(_context.cluster_node):
+            rc, out, err = utils.get_stdout_stderr("ssh {} crm_node 
--name".format(_context.cluster_node))
+            if rc != 0:
+                error(err)
+            peer_node = out
+        else:
+            peer_node = _context.cluster_node
+    return peer_node
+
+
+def is_online(crm_mon_txt):
+    """
+    Check whether local node is online
+    Besides that, in join process, check whether init node is online
+    """
+    if not re.search("Online: .* {} ".format(utils.this_node()), crm_mon_txt):
+        return False
+
+    # if peer_node is None, this is in the init process
+    peer_node = get_cluster_node_hostname()
+    if peer_node is None:
+        return True
+    # In join process
+    # If the joining node is already online but can't find the init node
+    # The communication IP maybe mis-configured
+    if not re.search("Online: .* {} ".format(peer_node), crm_mon_txt):
+        shutil.copy(COROSYNC_CONF_ORIG, corosync.conf())
+        csync2_update(corosync.conf())
+        stop_service("corosync")
+        print()
+        error("Cannot see peer node \"{}\", please check the communication 
IP".format(peer_node))
+    return True
+
+
 def pick_default_value(default_list, prev_list):
     """
     Provide default value for function 'prompt_for_string'.
@@ -1846,6 +1888,8 @@
         else:
             corosync.set_value("totem.nodeid", nodeid)
 
+    shutil.copy(corosync.conf(), COROSYNC_CONF_ORIG)
+
     # check if use IPv6
     ipv6_flag = False
     ipv6 = corosync.get_value("totem.ip_version")
@@ -1909,21 +1953,6 @@
                                               ringXaddr_res)
                 if not ringXaddr:
                     error("No value for ring{}".format(i))
-
-                # this check does not work on GCP (bsc#1106946)
-                if utils.detect_cloud() != "google-cloud-platform":
-                    _, outp = utils.get_stdout("ip addr show")
-                    tmp = re.findall(r' {}/[0-9]+ '.format(ringXaddr), outp, 
re.M)[0].strip()
-                    peer_ip = 
corosync.get_value("nodelist.node.ring{}_addr".format(i))
-                    # peer ring0_addr and local ring0_addr must be configured 
in the same network
-                    if not utils.ip_in_network(peer_ip, tmp):
-                        errmsg = "    Peer IP {} is not in the same network: 
{}".format(peer_ip, tmp)
-                        if _context.yes_to_all:
-                            error(errmsg)
-                        else:
-                            print(term.render(clidisplay.error(errmsg)))
-                            continue
-
                 ringXaddr_res.append(ringXaddr)
                 break
             if not rrp_flag:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.2.0+git.1580544897.c42c9530/crmsh/corosync.py 
new/crmsh-4.2.0+git.1581993539.5a1deb03/crmsh/corosync.py
--- old/crmsh-4.2.0+git.1580544897.c42c9530/crmsh/corosync.py   2020-02-01 
09:14:57.000000000 +0100
+++ new/crmsh-4.2.0+git.1581993539.5a1deb03/crmsh/corosync.py   2020-02-18 
03:38:59.000000000 +0100
@@ -811,24 +811,47 @@
     pass
 
 
-def add_node_ucast(IParray, node_id=None):
+def find_configured_ip(ip_list):
+    """
+    find if the same IP already configured
+    If so, raise IPAlreadyConfiguredError
+    """
+    with open(conf()) as f:
+        p = Parser(f.read())
+
+    # get exist ip list from corosync.conf
+    corosync_iplist = []
+    for path in set(p.all_paths()):
+        if re.search('nodelist.node.ring[0-9]*_addr', path):
+            corosync_iplist.extend(p.get_all(path))
+
+    # all_possible_ip is a ip set to check whether one of them already 
configured
+    all_possible_ip = set(ip_list)
+    # get local ip list
+    local_ip_list = utils.ip_in_local(utils.is_ipv6(ip_list[0]))
+    # extend all_possible_ip if ip_list contain local ip
+    # to avoid this scenarios in join node:
+    #   eth0's ip already configured in corosync.conf
+    #   eth1's ip also want to add in nodelist
+    # if this scenarios happened, raise IPAlreadyConfiguredError
+    if bool(set(ip_list) & set(local_ip_list)):
+        all_possible_ip |= set(local_ip_list)
+    configured_ip = list(all_possible_ip & set(corosync_iplist))
+    if configured_ip:
+        raise IPAlreadyConfiguredError("IP {} was already 
configured".format(','.join(configured_ip)))
+
+
+def add_node_ucast(ip_list, node_id=None):
+
+    find_configured_ip(ip_list)
 
     f = open(conf()).read()
     p = Parser(f)
 
-    # to check if the same IP already configured
-    exist_iplist = []
-    for path in p.all_paths():
-        if re.search('nodelist.node.ring[0-9]*_addr', path):
-            exist_iplist.extend(p.get_all(path))
-    for ip in IParray:
-        if ip in exist_iplist:
-            raise IPAlreadyConfiguredError("IP {} was already 
configured".format(ip))
-
     if node_id is None:
         node_id = get_free_nodeid(p)
     node_value = []
-    for i, addr in enumerate(IParray):
+    for i, addr in enumerate(ip_list):
         node_value += make_value('nodelist.node.ring{}_addr'.format(i), addr)
     node_value += make_value('nodelist.node.nodeid', str(node_id))
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/crmsh-4.2.0+git.1580544897.c42c9530/crmsh/utils.py 
new/crmsh-4.2.0+git.1581993539.5a1deb03/crmsh/utils.py
--- old/crmsh-4.2.0+git.1580544897.c42c9530/crmsh/utils.py      2020-02-01 
09:14:57.000000000 +0100
+++ new/crmsh-4.2.0+git.1581993539.5a1deb03/crmsh/utils.py      2020-02-18 
03:38:59.000000000 +0100
@@ -2083,6 +2083,11 @@
     def version(self):
         return self.addr.version
 
+
+def is_ipv6(addr):
+    return IP(addr).version() == 6
+
+
 # Set by detect_cloud() or iplist_for_cloud()
 # to avoid multiple requests
 _ip_for_cloud = None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.2.0+git.1580544897.c42c9530/test/features/bootstrap_bugs.feature 
new/crmsh-4.2.0+git.1581993539.5a1deb03/test/features/bootstrap_bugs.feature
--- 
old/crmsh-4.2.0+git.1580544897.c42c9530/test/features/bootstrap_bugs.feature    
    2020-02-01 09:14:57.000000000 +0100
+++ 
new/crmsh-4.2.0+git.1581993539.5a1deb03/test/features/bootstrap_bugs.feature    
    2020-02-18 03:38:59.000000000 +0100
@@ -33,3 +33,15 @@
     Then    Except "ERROR: cluster.geo_join: Space value not allowed for dest 
"node""
     When    Try "crm cluster geo-init-arbitrator -c ' '"
     Then    Except "ERROR: cluster.geo_init_arbitrator: Space value not 
allowed for dest "other""
+
+  @clean
+  Scenario: Setup cluster with crossed network(udpu only)
+    Given   Cluster service is "stopped" on "hanode1"
+    Given   Cluster service is "stopped" on "hanode2"
+    When    Run "crm cluster init -u -i eth0 -y --no-overwrite-sshkey" on 
"hanode1"
+    Then    Cluster service is "started" on "hanode1"
+    When    Try "crm cluster join -c hanode1 -i eth1 -y" on "hanode2"
+    Then    Cluster service is "stopped" on "hanode2"
+    And     Except "Cannot see peer node "hanode1", please check the 
communication IP" in stderr
+    When    Run "crm cluster join -c hanode1 -i eth0 -y" on "hanode2"
+    Then    Cluster service is "started" on "hanode2"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.2.0+git.1580544897.c42c9530/test/features/steps/step_implenment.py 
new/crmsh-4.2.0+git.1581993539.5a1deb03/test/features/steps/step_implenment.py
--- 
old/crmsh-4.2.0+git.1580544897.c42c9530/test/features/steps/step_implenment.py  
    2020-02-01 09:14:57.000000000 +0100
+++ 
new/crmsh-4.2.0+git.1581993539.5a1deb03/test/features/steps/step_implenment.py  
    2020-02-18 03:38:59.000000000 +0100
@@ -35,6 +35,11 @@
     context.stdout = out
 
 
+@when('Try "{cmd}" on "{addr}"')
+def step_impl(context, cmd, addr):
+    run_command_local_or_remote(context, cmd, addr, err_record=True)
+
+
 @when('Try "{cmd}"')
 def step_impl(context, cmd):
     run_command(context, cmd, err_record=True)
@@ -69,6 +74,12 @@
     context.command_error_output = None
 
 
+@then('Except "{msg}" in stderr')
+def step_impl(context, msg):
+    assert msg in context.command_error_output
+    context.command_error_output = None
+
+
 @then('Cluster service is "{state}" on "{addr}"')
 def step_impl(context, state, addr):
     assert check_cluster_state(context, state, addr) is True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.2.0+git.1580544897.c42c9530/test/features/steps/utils.py 
new/crmsh-4.2.0+git.1581993539.5a1deb03/test/features/steps/utils.py
--- old/crmsh-4.2.0+git.1580544897.c42c9530/test/features/steps/utils.py        
2020-02-01 09:14:57.000000000 +0100
+++ new/crmsh-4.2.0+git.1581993539.5a1deb03/test/features/steps/utils.py        
2020-02-18 03:38:59.000000000 +0100
@@ -19,14 +19,17 @@
     return out
 
 
-def run_command_local_or_remote(context, cmd, addr):
+def run_command_local_or_remote(context, cmd, addr, err_record=False):
     if addr == me():
-        out = run_command(context, cmd)
+        out = run_command(context, cmd, err_record)
         return out
     else:
         try:
             results = parallax.parallax_call([addr], cmd)
         except ValueError as err:
+            if err_record:
+                context.command_error_output = str(err)
+                return
             context.logger.error("\n{}\n".format(err))
             context.failed = True
         else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.2.0+git.1580544897.c42c9530/test/unittests/test_bootstrap.py 
new/crmsh-4.2.0+git.1581993539.5a1deb03/test/unittests/test_bootstrap.py
--- old/crmsh-4.2.0+git.1580544897.c42c9530/test/unittests/test_bootstrap.py    
2020-02-01 09:14:57.000000000 +0100
+++ new/crmsh-4.2.0+git.1581993539.5a1deb03/test/unittests/test_bootstrap.py    
2020-02-18 03:38:59.000000000 +0100
@@ -32,7 +32,6 @@
         Global setUp.
         """
 
-    #@mock.patch('crmsh.bootstrap.Context')
     def setUp(self):
         """
         Test setUp.
@@ -158,3 +157,128 @@
             mock.call(['10.10.10.1', '20.20.20.1'], '1'),
             mock.call(['10.10.10.2', '20.20.20.2'], '2')
         ])
+
+    @mock.patch('crmsh.utils.valid_ip_addr')
+    @mock.patch('crmsh.utils.get_stdout_stderr')
+    def test_get_cluster_node_hostname_None(self, mock_stdout_stderr, 
mock_valid_ip):
+        bootstrap._context = mock.Mock(cluster_node=None)
+
+        peer_node = bootstrap.get_cluster_node_hostname()
+        assert peer_node is None
+
+        mock_valid_ip.assert_not_called()
+        mock_stdout_stderr.assert_not_called()
+
+    @mock.patch('crmsh.utils.valid_ip_addr')
+    @mock.patch('crmsh.utils.get_stdout_stderr')
+    def test_get_cluster_node_hostname_IP(self, mock_stdout_stderr, 
mock_valid_ip):
+        bootstrap._context = mock.Mock(cluster_node="1.1.1.1")
+        mock_valid_ip.return_value = True
+        mock_stdout_stderr.return_value = (0, "node1", None)
+
+        peer_node = bootstrap.get_cluster_node_hostname()
+        assert peer_node == "node1"
+
+        mock_valid_ip.assert_called_once_with("1.1.1.1")
+        mock_stdout_stderr.assert_called_once_with("ssh 1.1.1.1 crm_node 
--name")
+
+    @mock.patch('crmsh.utils.valid_ip_addr')
+    @mock.patch('crmsh.utils.get_stdout_stderr')
+    def test_get_cluster_node_hostname_HOST(self, mock_stdout_stderr, 
mock_valid_ip):
+        bootstrap._context = mock.Mock(cluster_node="node2")
+        mock_valid_ip.return_value = False
+
+        peer_node = bootstrap.get_cluster_node_hostname()
+        assert peer_node == "node2"
+
+        mock_valid_ip.assert_called_once_with("node2")
+        mock_stdout_stderr.assert_not_called()
+
+    @mock.patch('crmsh.utils.this_node')
+    @mock.patch('re.search')
+    @mock.patch('crmsh.bootstrap.get_cluster_node_hostname')
+    def test_is_online_local_offline(self, mock_get_peer, mock_search, 
mock_this_node):
+        mock_this_node.return_value = "node1"
+        mock_search.return_value = None
+
+        assert bootstrap.is_online("text") is False
+
+        mock_this_node.assert_called_once_with()
+        mock_get_peer.assert_not_called()
+        mock_search.assert_called_once_with("Online: .* node1 ", "text")
+
+    @mock.patch('crmsh.utils.this_node')
+    @mock.patch('re.search')
+    @mock.patch('crmsh.bootstrap.get_cluster_node_hostname')
+    def test_is_online_on_init_node(self, mock_get_peer, mock_search, 
mock_this_node):
+        mock_search.return_value = mock.Mock()
+        mock_this_node.return_value = "node1"
+        mock_get_peer.return_value = None
+
+        assert bootstrap.is_online("text") is True
+
+        mock_this_node.assert_called_once_with()
+        mock_get_peer.assert_called_once_with()
+        mock_search.assert_called_once_with("Online: .* node1 ", "text")
+
+    @mock.patch('crmsh.bootstrap.error')
+    @mock.patch('crmsh.bootstrap.stop_service')
+    @mock.patch('crmsh.bootstrap.csync2_update')
+    @mock.patch('crmsh.corosync.conf')
+    @mock.patch('shutil.copy')
+    @mock.patch('crmsh.utils.this_node')
+    @mock.patch('re.search')
+    @mock.patch('crmsh.bootstrap.get_cluster_node_hostname')
+    def test_is_online_peer_offline(self, mock_get_peer, mock_search, 
mock_this_node,
+            mock_copy, mock_corosync_conf, mock_csync2, mock_stop_service, 
mock_error):
+        bootstrap.COROSYNC_CONF_ORIG = "/tmp/crmsh_tmpfile"
+        mock_search.side_effect = [ mock.Mock(), None ]
+        mock_this_node.return_value = "node2"
+        mock_get_peer.return_value = "node1"
+        mock_corosync_conf.side_effect = [ "/etc/corosync/corosync.conf", 
+                "/etc/corosync/corosync.conf"]
+
+        bootstrap.is_online("text")
+
+        mock_this_node.assert_called_once_with()
+        mock_get_peer.assert_called_once_with()
+        mock_search.assert_has_calls([
+            mock.call("Online: .* node2 ", "text"),
+            mock.call("Online: .* node1 ", "text")
+            ])
+        mock_corosync_conf.assert_has_calls([
+            mock.call(),
+            mock.call()
+            ])
+        mock_copy.assert_called_once_with(bootstrap.COROSYNC_CONF_ORIG, 
"/etc/corosync/corosync.conf")
+        mock_csync2.assert_called_once_with("/etc/corosync/corosync.conf")
+        mock_stop_service.assert_called_once_with("corosync")
+        mock_error.assert_called_once_with("Cannot see peer node \"node1\", 
please check the communication IP")
+
+    @mock.patch('crmsh.bootstrap.error')
+    @mock.patch('crmsh.bootstrap.stop_service')
+    @mock.patch('crmsh.bootstrap.csync2_update')
+    @mock.patch('crmsh.corosync.conf')
+    @mock.patch('shutil.copy')
+    @mock.patch('crmsh.utils.this_node')
+    @mock.patch('re.search')
+    @mock.patch('crmsh.bootstrap.get_cluster_node_hostname')
+    def test_is_online_both_online(self, mock_get_peer, mock_search, 
mock_this_node,
+            mock_copy, mock_corosync_conf, mock_csync2, mock_stop_service, 
mock_error):
+        mock_search.side_effect = [ mock.Mock(), mock.Mock() ]
+        mock_this_node.return_value = "node2"
+        mock_get_peer.return_value = "node1"
+
+        assert bootstrap.is_online("text") is True
+
+        mock_this_node.assert_called_once_with()
+        mock_get_peer.assert_called_once_with()
+        mock_search.assert_has_calls([
+            mock.call("Online: .* node2 ", "text"),
+            mock.call("Online: .* node1 ", "text")
+            ])
+        mock_corosync_conf.assert_not_called()
+        mock_copy.assert_not_called()
+        mock_csync2.assert_not_called()
+        mock_stop_service.assert_not_called()
+        mock_error.assert_not_called()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.2.0+git.1580544897.c42c9530/test/unittests/test_corosync.py 
new/crmsh-4.2.0+git.1581993539.5a1deb03/test/unittests/test_corosync.py
--- old/crmsh-4.2.0+git.1580544897.c42c9530/test/unittests/test_corosync.py     
2020-02-01 09:14:57.000000000 +0100
+++ new/crmsh-4.2.0+git.1581993539.5a1deb03/test/unittests/test_corosync.py     
2020-02-18 03:38:59.000000000 +0100
@@ -93,6 +93,60 @@
                            make_value('nodelist.node.nodeid', str(nid))))
         _valid(p)
         self.assertEqual(p.count('nodelist.node'), nid - 1)
+ 
+    @mock.patch("crmsh.utils.is_ipv6")
+    @mock.patch("crmsh.utils.ip_in_local")
+    @mock.patch("re.search")
+    @mock.patch("crmsh.corosync.Parser")
+    @mock.patch("crmsh.corosync.conf")
+    @mock.patch("builtins.open", new_callable=mock.mock_open, 
read_data="corosync conf data")
+    def test_find_configured_ip_no_exception(self, mock_open_file, mock_conf, 
mock_parser, mock_search, mock_ip_local, mock_isv6):
+        mock_conf.return_value = "/etc/corosync/corosync.conf"
+        mock_parser_inst = mock.Mock()
+        mock_parser.return_value = mock_parser_inst
+        mock_parser_inst.all_paths.return_value = ["nodelist.node.ring0_addr"]
+        mock_search.return_value = mock.Mock()
+        mock_parser_inst.get_all.return_value = ["10.10.10.1"]
+        mock_isv6.return_value = False
+        mock_ip_local.return_value = ["192.168.1.1", "10.10.10.2", 
"20.20.20.2"]
+
+        corosync.find_configured_ip(["10.10.10.2"])
+
+        mock_conf.assert_called_once_with()
+        mock_parser_inst.all_paths.assert_called_once_with()
+        
mock_parser_inst.get_all.assert_called_once_with("nodelist.node.ring0_addr")
+        mock_open_file.assert_called_once_with(mock_conf.return_value)
+        mock_isv6.assert_called_once_with("10.10.10.2")
+        mock_ip_local.assert_called_once_with(False)
+        mock_search.assert_called_once_with("nodelist.node.ring[0-9]*_addr", 
"nodelist.node.ring0_addr")
+
+    @mock.patch("crmsh.utils.is_ipv6")
+    @mock.patch("crmsh.utils.ip_in_local")
+    @mock.patch("re.search")
+    @mock.patch("crmsh.corosync.Parser")
+    @mock.patch("crmsh.corosync.conf")
+    @mock.patch("builtins.open", new_callable=mock.mock_open, 
read_data="corosync conf data")
+    def test_find_configured_ip_exception(self, mock_open_file, mock_conf, 
mock_parser, mock_search, mock_ip_local, mock_isv6):
+        mock_conf.return_value = "/etc/corosync/corosync.conf"
+        mock_parser_inst = mock.Mock()
+        mock_parser.return_value = mock_parser_inst
+        mock_parser_inst.all_paths.return_value = ["nodelist.node.ring0_addr"]
+        mock_search.return_value = mock.Mock()
+        mock_parser_inst.get_all.return_value = ["10.10.10.1", "10.10.10.2"]
+        mock_isv6.return_value = False
+        mock_ip_local.return_value = ["192.168.1.1", "10.10.10.2", 
"20.20.20.2"]
+
+        with self.assertRaises(corosync.IPAlreadyConfiguredError) as err:
+            corosync.find_configured_ip(["10.10.10.2"])
+        self.assertEqual("IP 10.10.10.2 was already configured", 
str(err.exception))
+
+        mock_conf.assert_called_once_with()
+        mock_parser_inst.all_paths.assert_called_once_with()
+        
mock_parser_inst.get_all.assert_called_once_with("nodelist.node.ring0_addr")
+        mock_open_file.assert_called_once_with(mock_conf.return_value)
+        mock_isv6.assert_called_once_with("10.10.10.2")
+        mock_ip_local.assert_called_once_with(False)
+        mock_search.assert_called_once_with("nodelist.node.ring[0-9]*_addr", 
"nodelist.node.ring0_addr")
 
     def test_add_node_ucast(self):
         from crmsh.corosync import add_node_ucast, get_values


Reply via email to