Statistics
| Branch: | Tag: | Revision:

root / test / py / cmdlib / testsupport / rpc_runner_mock.py @ bd39b6bb

History | View | Annotate | Download (4.8 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

    
22
"""Support for mocking the RPC runner"""
23

    
24

    
25
import mock
26

    
27
from ganeti import objects
28
from ganeti import rpc
29

    
30

    
31
def CreateRpcRunnerMock():
32
  """Creates a new L{mock.MagicMock} tailored for L{rpc.RpcRunner}
33

34
  """
35
  ret = mock.MagicMock(spec=rpc.RpcRunner)
36
  return ret
37

    
38

    
39
class RpcResultsBuilder(object):
40
  """Helper class which assists in constructing L{rpc.RpcResult} objects.
41

42
  This class provides some convenience methods for constructing L{rpc.RpcResult}
43
  objects. It is possible to create single results with the C{Create*} methods
44
  or to create multi-node results by repeatedly calling the C{Add*} methods and
45
  then obtaining the final result with C{Build}.
46

47
  The C{node} parameter of all the methods can either be a L{objects.Node}
48
  object, a node UUID or a node name. You have to provide the cluster config
49
  in the constructor if you want to use node UUID's/names.
50

51
  A typical usage of this class is as follows::
52

53
    self.rpc.call_some_rpc.return_value = \
54
      RpcResultsBuilder(cfg=self.cfg) \
55
        .AddSuccessfulNode(node1,
56
                           {
57
                             "result_key": "result_data",
58
                             "another_key": "other_data",
59
                           }) \
60
        .AddErrorNode(node2) \
61
        .Build()
62

63
  """
64

    
65
  def __init__(self, cfg=None, use_node_names=False):
66
    """Constructor.
67

68
    @type cfg: L{ganeti.config.ConfigWriter}
69
    @param cfg: used to resolve nodes if not C{None}
70
    @type use_node_names: bool
71
    @param use_node_names: if set to C{True}, the node field in the RPC results
72
          will contain the node name instead of the node UUID.
73
    """
74
    self._cfg = cfg
75
    self._use_node_names = use_node_names
76
    self._results = []
77

    
78
  def _GetNode(self, node_id):
79
    if isinstance(node_id, objects.Node):
80
      return node_id
81

    
82
    node = None
83
    if self._cfg is not None:
84
      node = self._cfg.GetNodeInfo(node_id)
85
      if node is None:
86
        node = self._cfg.GetNodeInfoByName(node_id)
87

    
88
    assert node is not None, "Failed to find '%s' in configuration" % node_id
89
    return node
90

    
91
  def _GetNodeId(self, node_id):
92
    node = self._GetNode(node_id)
93
    if self._use_node_names:
94
      return node.name
95
    else:
96
      return node.uuid
97

    
98
  def CreateSuccessfulNodeResult(self, node, data=None):
99
    """@see L{RpcResultsBuilder}
100

101
    @param node: @see L{RpcResultsBuilder}.
102
    @type data: dict
103
    @param data: the data as returned by the RPC
104
    @rtype: L{rpc.RpcResult}
105
    """
106
    if data is None:
107
      data = {}
108
    return rpc.RpcResult(data=(True, data), node=self._GetNodeId(node))
109

    
110
  def CreateFailedNodeResult(self, node):
111
    """@see L{RpcResultsBuilder}
112

113
    @param node: @see L{RpcResultsBuilder}.
114
    @rtype: L{rpc.RpcResult}
115
    """
116
    return rpc.RpcResult(failed=True, node=self._GetNodeId(node))
117

    
118
  def CreateOfflineNodeResult(self, node):
119
    """@see L{RpcResultsBuilder}
120

121
    @param node: @see L{RpcResultsBuilder}.
122
    @rtype: L{rpc.RpcResult}
123
    """
124
    return rpc.RpcResult(failed=True, node=self._GetNodeId(node))
125

    
126
  def CreateErrorNodeResult(self, node, error_msg=None):
127
    """@see L{RpcResultsBuilder}
128

129
    @param node: @see L{RpcResultsBuilder}.
130
    @type error_msg: string
131
    @param error_msg: the error message as returned by the RPC
132
    @rtype: L{rpc.RpcResult}
133
    """
134
    return rpc.RpcResult(data=(False, error_msg), node=self._GetNodeId(node))
135

    
136
  def AddSuccessfulNode(self, node, data=None):
137
    """@see L{CreateSuccessfulNode}"""
138
    self._results.append(self.CreateSuccessfulNodeResult(node, data))
139
    return self
140

    
141
  def AddFailedNode(self, node):
142
    """@see L{CreateFailedNode}"""
143
    self._results.append(self.CreateFailedNodeResult(node))
144
    return self
145

    
146
  def AddOfflineNode(self, node):
147
    """@see L{CreateOfflineNode}"""
148
    self._results.append(self.CreateOfflineNodeResult(node))
149

    
150
  def AddErrorNode(self, node, error_msg=None):
151
    """@see L{CreateErrorNode}"""
152
    self._results.append(self.CreateErrorNodeResult(node, error_msg=error_msg))
153

    
154
  def Build(self):
155
    """Creates a dictionary holding multi-node results
156

157
    @rtype: dict
158
    """
159
    return dict((result.node, result) for result in self._results)