root / test / py / cmdlib / testsupport / rpc_runner_mock.py @ 3efa7659
History | View | Annotate | Download (4.7 kB)
1 |
#
|
---|---|
2 |
#
|
3 |
|
4 |
# Copyright (C) 2013 Google Inc.
|
5 |
#
|
6 |
# This program is free software; you can redistribute it and/or modify
|
7 |
# it under the terms of the GNU General Public License as published by
|
8 |
# the Free Software Foundation; either version 2 of the License, or
|
9 |
# (at your option) any later version.
|
10 |
#
|
11 |
# This program is distributed in the hope that it will be useful, but
|
12 |
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 |
# General Public License for more details.
|
15 |
#
|
16 |
# You should have received a copy of the GNU General Public License
|
17 |
# along with this program; if not, write to the Free Software
|
18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
19 |
# 02110-1301, USA.
|
20 |
|
21 |
import mock |
22 |
|
23 |
from ganeti import objects |
24 |
from ganeti import rpc |
25 |
|
26 |
|
27 |
def CreateRpcRunnerMock(): |
28 |
"""Creates a new L{mock.MagicMock} tailored for L{rpc.RpcRunner}
|
29 |
|
30 |
"""
|
31 |
ret = mock.MagicMock(spec=rpc.RpcRunner) |
32 |
return ret
|
33 |
|
34 |
|
35 |
class RpcResultsBuilder(object): |
36 |
"""Helper class which assists in constructing L{rpc.RpcResult} objects.
|
37 |
|
38 |
This class provides some convenience methods for constructing L{rpc.RpcResult}
|
39 |
objects. It is possible to create single results with the C{Create*} methods
|
40 |
or to create multi-node results by repeatedly calling the C{Add*} methods and
|
41 |
then obtaining the final result with C{Build}.
|
42 |
|
43 |
The C{node} parameter of all the methods can either be a L{objects.Node}
|
44 |
object, a node UUID or a node name. You have to provide the cluster config
|
45 |
in the constructor if you want to use node UUID's/names.
|
46 |
|
47 |
A typical usage of this class is as follows::
|
48 |
|
49 |
self.rpc.call_some_rpc.return_value = \
|
50 |
RpcResultsBuilder(cfg=self.cfg) \
|
51 |
.AddSuccessfulNode(node1,
|
52 |
{
|
53 |
"result_key": "result_data",
|
54 |
"another_key": "other_data",
|
55 |
}) \
|
56 |
.AddErrorNode(node2) \
|
57 |
.Build()
|
58 |
|
59 |
"""
|
60 |
|
61 |
def __init__(self, cfg=None, use_node_names=False): |
62 |
"""Constructor.
|
63 |
|
64 |
@type cfg: L{ganeti.config.ConfigWriter}
|
65 |
@param cfg: used to resolve nodes if not C{None}
|
66 |
@type use_node_names: bool
|
67 |
@param use_node_names: if set to C{True}, the node field in the RPC results
|
68 |
will contain the node name instead of the node UUID.
|
69 |
"""
|
70 |
self._cfg = cfg
|
71 |
self._use_node_names = use_node_names
|
72 |
self._results = []
|
73 |
|
74 |
def _GetNode(self, node_id): |
75 |
if isinstance(node_id, objects.Node): |
76 |
return node_id
|
77 |
|
78 |
node = None
|
79 |
if self._cfg is not None: |
80 |
node = self._cfg.GetNodeInfo(node_id)
|
81 |
if node is None: |
82 |
node = self._cfg.GetNodeInfoByName(node_id)
|
83 |
|
84 |
assert node is not None, "Failed to find '%s' in configuration" % node_id |
85 |
return node
|
86 |
|
87 |
def _GetNodeId(self, node_id): |
88 |
node = self._GetNode(node_id)
|
89 |
if self._use_node_names: |
90 |
return node.name
|
91 |
else:
|
92 |
return node.uuid
|
93 |
|
94 |
def CreateSuccessfulNodeResult(self, node, data={}): |
95 |
"""@see L{RpcResultsBuilder}
|
96 |
|
97 |
@param node: @see L{RpcResultsBuilder}.
|
98 |
@type data: dict
|
99 |
@param data: the data as returned by the RPC
|
100 |
@rtype: L{rpc.RpcResult}
|
101 |
"""
|
102 |
return rpc.RpcResult(data=(True, data), node=self._GetNodeId(node)) |
103 |
|
104 |
def CreateFailedNodeResult(self, node): |
105 |
"""@see L{RpcResultsBuilder}
|
106 |
|
107 |
@param node: @see L{RpcResultsBuilder}.
|
108 |
@rtype: L{rpc.RpcResult}
|
109 |
"""
|
110 |
return rpc.RpcResult(failed=True, node=self._GetNodeId(node)) |
111 |
|
112 |
def CreateOfflineNodeResult(self, node): |
113 |
"""@see L{RpcResultsBuilder}
|
114 |
|
115 |
@param node: @see L{RpcResultsBuilder}.
|
116 |
@rtype: L{rpc.RpcResult}
|
117 |
"""
|
118 |
return rpc.RpcResult(failed=True, node=self._GetNodeId(node)) |
119 |
|
120 |
def CreateErrorNodeResult(self, node, error_msg=None): |
121 |
"""@see L{RpcResultsBuilder}
|
122 |
|
123 |
@param node: @see L{RpcResultsBuilder}.
|
124 |
@type error_msg: string
|
125 |
@param error_msg: the error message as returned by the RPC
|
126 |
@rtype: L{rpc.RpcResult}
|
127 |
"""
|
128 |
return rpc.RpcResult(data=(False, error_msg), node=self._GetNodeId(node)) |
129 |
|
130 |
def AddSuccessfulNode(self, node, data={}): |
131 |
"""@see L{CreateSuccessfulNode}"""
|
132 |
self._results.append(self.CreateSuccessfulNodeResult(node, data)) |
133 |
return self |
134 |
|
135 |
def AddFailedNode(self, node): |
136 |
"""@see L{CreateFailedNode}"""
|
137 |
self._results.append(self.CreateFailedNodeResult(node)) |
138 |
return self |
139 |
|
140 |
def AddOfflineNode(self, node): |
141 |
"""@see L{CreateOfflineNode}"""
|
142 |
self._results.append(self.CreateOfflineNodeResult(node)) |
143 |
|
144 |
def AddErrorNode(self, node, error_msg=None): |
145 |
"""@see L{CreateErrorNode}"""
|
146 |
self._results.append(self.CreateErrorNodeResult(node, error_msg=error_msg)) |
147 |
|
148 |
def Build(self): |
149 |
"""Creates a dictionary holding multi-node results
|
150 |
|
151 |
@rtype: dict
|
152 |
"""
|
153 |
return dict((result.node, result) for result in self._results) |