On Tue, 21 Apr 2015 at 14:37 Petr Pudlak <[email protected]> wrote:
> On Thu, Apr 16, 2015 at 05:31:58PM +0200, 'Helga Velroyen' via
> ganeti-devel wrote:
> >So far the backend function NodeSshKeyAdd naively assumed
> >that all nodes are online and reachable via SSH. This
> >patch adds offline status information to the function's
> >signature to respect the offline status when updating
> >SSH keys.
> >
> >Signed-off-by: Helga Velroyen <[email protected]>
> >---
> > lib/backend.py | 4 ++++
> > test/py/ganeti.backend_unittest.py | 41
> ++++++++++++++++++++++++++++++++++++++
> > test/py/testutils_ssh.py | 4 ++++
> > 3 files changed, 49 insertions(+)
> >
> >diff --git a/lib/backend.py b/lib/backend.py
> >index 04b8350..b5f4001 100644
> >--- a/lib/backend.py
> >+++ b/lib/backend.py
> >@@ -1544,10 +1544,14 @@ def AddNodeSshKey(node_uuid, node_name,
> >
> > all_nodes = ssconf_store.GetNodeList()
> > master_node = ssconf_store.GetMasterNode()
> >+ online_nodes = ssconf_store.GetOnlineNodeList()
> >
> > for node in all_nodes:
> > if node == master_node:
> > continue
> >+ if node not in online_nodes:
> >+ logging.debug("Skipping offline node '%s'.", node)
> >+ continue
> > if node in potential_master_candidates:
> > run_cmd_fn(cluster_name, node, pathutils.SSH_UPDATE,
> > ssh_port_map.get(node), pot_mc_data,
> >diff --git a/test/py/ganeti.backend_unittest.py b/test/py/
> ganeti.backend_unittest.py
> >index cd2e24c..56200ea 100755
> >--- a/test/py/ganeti.backend_unittest.py
> >+++ b/test/py/ganeti.backend_unittest.py
> >@@ -971,6 +971,7 @@ class
> TestAddRemoveGenerateNodeSshKey(testutils.GanetiTestCase):
> > self._ssconf_mock.GetNodeList = mock.Mock()
> > self._ssconf_mock.GetMasterNode = mock.Mock()
> > self._ssconf_mock.GetClusterName = mock.Mock()
> >+ self._ssconf_mock.GetOnlineNodeList = mock.Mock()
> >
> > self._run_cmd_mock = mock.Mock()
> > self._run_cmd_mock.side_effect = self._ssh_file_manager.RunCommand
> >@@ -1034,6 +1035,7 @@ class
> TestAddRemoveGenerateNodeSshKey(testutils.GanetiTestCase):
> > self._ssconf_mock.GetNodeList.reset_mock()
> > self._ssconf_mock.GetMasterNode.reset_mock()
> > self._ssconf_mock.GetClusterName.reset_mock()
> >+ self._ssconf_mock.GetOnlineNodeList.reset_mock()
> > self._run_cmd_mock.reset_mock()
> >
> > self._ssh_file_manager.InitAllNodes(15, 10, 5)
> >@@ -1046,6 +1048,7 @@ class
> TestAddRemoveGenerateNodeSshKey(testutils.GanetiTestCase):
> > self._all_nodes = self._ssh_file_manager.GetAllNodeNames()
> >
> > self._ssconf_mock.GetNodeList.return_value = self._all_nodes
> >+ self._ssconf_mock.GetOnlineNodeList.return_value = self._all_nodes
> >
> > def _TearDownTestData(self):
> > os.remove(self._pub_key_file)
> >@@ -1355,6 +1358,44 @@ class
> TestAddRemoveGenerateNodeSshKey(testutils.GanetiTestCase):
> >
> > self._TearDownTestData()
> >
> >+ def testAddKeyWithOfflineNodes(self):
> >+ new_node_name = "new_node_name"
> >+ new_node_uuid = "new_node_uuid"
> >+ new_node_key = "new_node_key"
> >+ is_master_candidate = True
> >+ is_potential_master_candidate = True
> >+ is_master = False
> >+
> >+ self._SetupTestData()
> >+ self._AddNewNodeToTestData(
> >+ new_node_name, new_node_uuid, new_node_key,
> >+ is_potential_master_candidate, is_master_candidate,
> >+ is_master)
> >+
> >+ # 'randomly' mark some nodes as offline
> >+ self._online_nodes = [name for name in self._all_nodes
> >+ if '3' not in name and '5' not in name]
> >+ self._ssconf_mock.GetOnlineNodeList.return_value = self._online_nodes
> >+ backend.AddNodeSshKey(new_node_uuid, new_node_name,
> >+ self._potential_master_candidates,
> >+ self._ssh_port_map,
> >+ to_authorized_keys=is_master_candidate,
> >+ to_public_keys=is_potential_master_candidate,
> >+ get_public_keys=is_potential_master_candidate,
> >+ pub_key_file=self._pub_key_file,
> >+ ssconf_store=self._ssconf_mock,
> >+ noded_cert_file=self.noded_cert_file,
> >+ run_cmd_fn=self._run_cmd_mock)
> >+
> >+ for node in self._all_nodes:
> >+ if node in self._online_nodes:
> >+ self.assertTrue(self._ssh_file_manager.NodeHasAuthorizedKey(
> >+ node, new_node_key))
> >+ else:
> >+ self.assertFalse(self._ssh_file_manager.NodeHasAuthorizedKey(
> >+ node, new_node_key))
> >+
> >+ self._TearDownTestData()
> >
> > class TestVerifySshSetup(testutils.GanetiTestCase):
> >
> >diff --git a/test/py/testutils_ssh.py b/test/py/testutils_ssh.py
> >index 0220c50..a65c44e 100644
> >--- a/test/py/testutils_ssh.py
> >+++ b/test/py/testutils_ssh.py
> >@@ -150,6 +150,10 @@ class FakeSshFileManager(object):
> > port_map[node] = port
> > return port_map
> >
> >+ def GetOfflineMap(self):
> >+ """Returns a dict indicating that all nodes are online."""
> >+ return dict([(name, False) for name in self._all_node_data.keys()])
>
> This function doesn't seem to be used anywhere. Perhaps something left
> after
> a refactoring?
>
Good catch! Thanks for spotting this!
>
> >+
> > def GetAllNodeNames(self):
> > return self._all_node_data.keys()
> >
> >--
> >2.2.0.rc0.207.ga3a616c
> >
>
> Rest LGTM, thanks
>
FYI, interdiff:
diff --git a/test/py/testutils_ssh.py b/test/py/testutils_ssh.py
index 9ac4725..dab5412 100644
--- a/test/py/testutils_ssh.py
+++ b/test/py/testutils_ssh.py
@@ -136,10 +136,6 @@ class FakeSshFileManager(object):
port_map[node] = port
return port_map
- def GetOfflineMap(self):
- """Returns a dict indicating that all nodes are online."""
- return dict([(name, False) for name in self._all_node_data.keys()])
-
def GetAllNodeNames(self):
return self._all_node_data.keys()
Cheers,
Helga