diff --git a/lib/rpc.py b/lib/rpc.py index cb0ca7847ee6648511605f64da032926c7475362..126984516a43d679d9648d5b13dd3eff5ef304c2 100644 --- a/lib/rpc.py +++ b/lib/rpc.py @@ -285,7 +285,7 @@ class _StaticResolver: return zip(hosts, self._addresses) -def _CheckConfigNode(name, node): +def _CheckConfigNode(name, node, accept_offline_node): """Checks if a node is online. @type name: string @@ -297,24 +297,29 @@ def _CheckConfigNode(name, node): if node is None: # Depend on DNS for name resolution ip = name - elif node.offline: + elif node.offline and not accept_offline_node: ip = _OFFLINE else: ip = node.primary_ip return (name, ip) -def _NodeConfigResolver(single_node_fn, all_nodes_fn, hosts, _): +def _NodeConfigResolver(single_node_fn, all_nodes_fn, hosts, opts): """Calculate node addresses using configuration. """ + accept_offline_node = (opts is rpc_defs.ACCEPT_OFFLINE_NODE) + + assert accept_offline_node or opts is None, "Unknown option" + # Special case for single-host lookups if len(hosts) == 1: (name, ) = hosts - return [_CheckConfigNode(name, single_node_fn(name))] + return [_CheckConfigNode(name, single_node_fn(name), accept_offline_node)] else: all_nodes = all_nodes_fn() - return [_CheckConfigNode(name, all_nodes.get(name, None)) + return [_CheckConfigNode(name, all_nodes.get(name, None), + accept_offline_node) for name in hosts] diff --git a/lib/rpc_defs.py b/lib/rpc_defs.py index 2e32c82e9accca455b019d784be330eac807bf80..657776ff4eb3d9bbbf58ca7e761db99afaa28768 100644 --- a/lib/rpc_defs.py +++ b/lib/rpc_defs.py @@ -58,6 +58,8 @@ TMO_1DAY = 86400 SINGLE = "single-node" MULTI = "multi-node" +ACCEPT_OFFLINE_NODE = object() + # Constants for encoding/decoding (ED_OBJECT_DICT, ED_OBJECT_DICT_LIST, diff --git a/test/ganeti.rpc_unittest.py b/test/ganeti.rpc_unittest.py index 633d89a54ec76705d43024e553ce2f7e241a5c2f..da94a7089ab0f1203f6a0044f83bac755d764935 100755 --- a/test/ganeti.rpc_unittest.py +++ b/test/ganeti.rpc_unittest.py @@ -28,6 +28,7 @@ import unittest from ganeti import constants from ganeti import compat from ganeti import rpc +from ganeti import rpc_defs from ganeti import http from ganeti import errors from ganeti import serializer @@ -397,6 +398,17 @@ class TestNodeConfigResolver(unittest.TestCase): ["node100.example.com"], None), [("node100.example.com", rpc._OFFLINE)]) + def testSingleOfflineWithAcceptOffline(self): + fn = self._GetSingleOfflineNode + assert fn("node100.example.com").offline + self.assertEqual(rpc._NodeConfigResolver(fn, NotImplemented, + ["node100.example.com"], + rpc_defs.ACCEPT_OFFLINE_NODE), + [("node100.example.com", "192.0.2.100")]) + for i in [False, True, "", "Hello", 0, 1]: + self.assertRaises(AssertionError, rpc._NodeConfigResolver, + fn, NotImplemented, ["node100.example.com"], i) + def testUnknownSingleNode(self): self.assertEqual(rpc._NodeConfigResolver(lambda _: None, NotImplemented, ["node110.example.com"], None),