This patch adds a unit test where SSH keys of a diverse
set of nodes is removed. By 'diverse', we mean a set
consisting of master candidates, potential master
candidates, and normal nodes.

It also fixes some minor bug that surfaced with that
test.

Signed-off-by: Helga Velroyen <[email protected]>
---
 lib/backend.py                     |  4 +++-
 test/py/ganeti.backend_unittest.py | 33 +++++++++++++++++++++++++++++++++
 test/py/testutils_ssh.py           | 37 +++++++++++++++++++++++++++++++++++++
 3 files changed, 73 insertions(+), 1 deletion(-)

diff --git a/lib/backend.py b/lib/backend.py
index cfc6ec8..35f8c47 100644
--- a/lib/backend.py
+++ b/lib/backend.py
@@ -1930,7 +1930,9 @@ def RemoveNodeSshKeyBulk(node_list,
   all_keys_to_remove = {}
   if from_authorized_keys or from_public_keys:
     for node_info in node_list:
-
+      # Skip nodes that don't actually need any keys to be removed.
+      if not (node_info.from_authorized_keys or node_info.from_public_keys):
+        continue
       if keys_to_remove:
         keys = keys_to_remove
       else:
diff --git a/test/py/ganeti.backend_unittest.py 
b/test/py/ganeti.backend_unittest.py
index 80845b2..94424ce 100755
--- a/test/py/ganeti.backend_unittest.py
+++ b/test/py/ganeti.backend_unittest.py
@@ -1509,6 +1509,39 @@ class 
TestAddRemoveGenerateNodeSshKey(testutils.GanetiTestCase):
       self.assertEqual(1,
           len(self._ssh_file_manager.GetAuthorizedKeysOfNode(node_info.name)))
 
+  def testRemoveDiverseNodesBulk(self):
+    node_list = []
+    key_map = {}
+    for node_name, (node_uuid, node_key, is_potential_master_candidate,
+                    is_master_candidate, _) in \
+        self._ssh_file_manager.GetAllNodesDiverse()[:3]:
+      node_list.append(backend.SshRemoveNodeInfo(
+          uuid=node_uuid,
+          name=node_name,
+          from_authorized_keys=is_master_candidate,
+          from_public_keys=is_potential_master_candidate,
+          clear_authorized_keys=True,
+          clear_public_keys=True))
+      key_map[node_name] = node_key
+
+    backend.RemoveNodeSshKeyBulk(node_list,
+                                 self._master_candidate_uuids,
+                                 self._potential_master_candidates,
+                                 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_info in node_list:
+      self._ssh_file_manager.AssertNoNodeHasPublicKey(
+          node_info.uuid, key_map[node_info.name])
+      self._ssh_file_manager.AssertNodeSetOnlyHasAuthorizedKey(
+          [node_info.name], key_map[node_info.name])
+      self.assertEqual(0,
+          len(self._ssh_file_manager.GetPublicKeysOfNode(node_info.name)))
+      self.assertEqual(1,
+          len(self._ssh_file_manager.GetAuthorizedKeysOfNode(node_info.name)))
+
   def testDemoteMasterCandidateToPotentialMasterCandidate(self):
     node_name, node_info = self._ssh_file_manager.GetAllMasterCandidates()[0]
     self._ssh_file_manager.SetOrAddNode(
diff --git a/test/py/testutils_ssh.py b/test/py/testutils_ssh.py
index 7dbb6fb..d00b3c4 100644
--- a/test/py/testutils_ssh.py
+++ b/test/py/testutils_ssh.py
@@ -203,6 +203,43 @@ class FakeSshFileManager(object):
             in self._all_node_data.items() if not node_info.is_master_candidate
             and not node_info.is_potential_master_candidate]
 
+  def GetAllNodesDiverse(self):
+    """This returns all nodes in a diverse order.
+
+    This will return all nodes, but makes sure that they ordered so that
+    the list will contain in a round-robin fashion, a master candidate,
+    a potential master candidate, a normal node, then again a master
+    candidate, etc.
+
+    """
+    master_candidates = self.GetAllMasterCandidates()
+    potential_master_candidates = self.GetAllPurePotentialMasterCandidates()
+    normal_nodes = self.GetAllNormalNodes()
+
+    mixed_list = []
+
+    i = 0
+
+    assert (len(self._all_node_data) == len(master_candidates)
+            + len(potential_master_candidates) + len(normal_nodes))
+
+    while len(mixed_list) < len(self._all_node_data):
+      if i % 3 == 0:
+        if master_candidates:
+          mixed_list.append(master_candidates[0])
+          master_candidates = master_candidates[1:]
+      elif i % 3 == 1:
+        if potential_master_candidates:
+          mixed_list.append(potential_master_candidates[0])
+          potential_master_candidates = potential_master_candidates[1:]
+      else:  # i % 3 == 2
+        if normal_nodes:
+          mixed_list.append(normal_nodes[0])
+          normal_nodes = normal_nodes[1:]
+      i += 1
+
+    return mixed_list
+
   def GetPublicKeysOfNode(self, node):
     return self._public_keys[node]
 
-- 
2.6.0.rc2.230.g3dd15c0

Reply via email to