Statistics
| Branch: | Tag: | Revision:

root / lib / rpc / node.py @ 31d3b918

History | View | Annotate | Download (31.5 kB)

1 2f31098c Iustin Pop
#
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 91c17910 Iustin Pop
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Google Inc.
5 a8083063 Iustin Pop
#
6 a8083063 Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 a8083063 Iustin Pop
# it under the terms of the GNU General Public License as published by
8 a8083063 Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 a8083063 Iustin Pop
# (at your option) any later version.
10 a8083063 Iustin Pop
#
11 a8083063 Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 a8083063 Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 a8083063 Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 a8083063 Iustin Pop
# General Public License for more details.
15 a8083063 Iustin Pop
#
16 a8083063 Iustin Pop
# You should have received a copy of the GNU General Public License
17 a8083063 Iustin Pop
# along with this program; if not, write to the Free Software
18 a8083063 Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 a8083063 Iustin Pop
# 02110-1301, USA.
20 a8083063 Iustin Pop
21 a8083063 Iustin Pop
22 3ef3c771 Iustin Pop
"""Inter-node RPC library.
23 a8083063 Iustin Pop

24 a8083063 Iustin Pop
"""
25 a8083063 Iustin Pop
26 b459a848 Andrea Spadaccini
# pylint: disable=C0103,R0201,R0904
27 72737a7f Iustin Pop
# C0103: Invalid name, since call_ are not valid
28 72737a7f Iustin Pop
# R0201: Method could be a function, we keep all rpcs instance methods
29 72737a7f Iustin Pop
# as not to change them back and forth between static/instance methods
30 72737a7f Iustin Pop
# if they need to start using instance attributes
31 72737a7f Iustin Pop
# R0904: Too many public methods
32 a8083063 Iustin Pop
33 58b311ca Iustin Pop
import logging
34 12bce260 Michael Hanselmann
import zlib
35 12bce260 Michael Hanselmann
import base64
36 33231500 Michael Hanselmann
import pycurl
37 33231500 Michael Hanselmann
import threading
38 cbe4a0a5 Dimitris Aragiorgis
import copy
39 a8083063 Iustin Pop
40 a8083063 Iustin Pop
from ganeti import utils
41 a8083063 Iustin Pop
from ganeti import objects
42 ecfe9491 Michael Hanselmann
from ganeti import http
43 7c28c575 Michael Hanselmann
from ganeti import serializer
44 eafd8762 Michael Hanselmann
from ganeti import constants
45 781de953 Iustin Pop
from ganeti import errors
46 a744b676 Manuel Franceschini
from ganeti import netutils
47 eb202c13 Manuel Franceschini
from ganeti import ssconf
48 9a914f7a René Nussbaumer
from ganeti import runtime
49 00267bfe Michael Hanselmann
from ganeti import compat
50 cd40dc53 Michael Hanselmann
from ganeti import rpc_defs
51 80ec9f96 Michael Hanselmann
from ganeti import pathutils
52 cffbbae7 Michael Hanselmann
from ganeti import vcluster
53 a8083063 Iustin Pop
54 200de241 Michael Hanselmann
# Special module generated at build time
55 200de241 Michael Hanselmann
from ganeti import _generated_rpc
56 200de241 Michael Hanselmann
57 fe267188 Iustin Pop
# pylint has a bug here, doesn't see this import
58 b459a848 Andrea Spadaccini
import ganeti.http.client  # pylint: disable=W0611
59 ae88ef45 Michael Hanselmann
60 a8083063 Iustin Pop
61 33231500 Michael Hanselmann
_RPC_CLIENT_HEADERS = [
62 33231500 Michael Hanselmann
  "Content-type: %s" % http.HTTP_APP_JSON,
63 8e29563f Iustin Pop
  "Expect:",
64 33231500 Michael Hanselmann
  ]
65 4331f6cd Michael Hanselmann
66 00267bfe Michael Hanselmann
#: Special value to describe an offline host
67 00267bfe Michael Hanselmann
_OFFLINE = object()
68 00267bfe Michael Hanselmann
69 4331f6cd Michael Hanselmann
70 4331f6cd Michael Hanselmann
def Init():
71 4331f6cd Michael Hanselmann
  """Initializes the module-global HTTP client manager.
72 4331f6cd Michael Hanselmann

73 33231500 Michael Hanselmann
  Must be called before using any RPC function and while exactly one thread is
74 33231500 Michael Hanselmann
  running.
75 4331f6cd Michael Hanselmann

76 4331f6cd Michael Hanselmann
  """
77 33231500 Michael Hanselmann
  # curl_global_init(3) and curl_global_cleanup(3) must be called with only
78 33231500 Michael Hanselmann
  # one thread running. This check is just a safety measure -- it doesn't
79 33231500 Michael Hanselmann
  # cover all cases.
80 33231500 Michael Hanselmann
  assert threading.activeCount() == 1, \
81 33231500 Michael Hanselmann
         "Found more than one active thread when initializing pycURL"
82 4331f6cd Michael Hanselmann
83 33231500 Michael Hanselmann
  logging.info("Using PycURL %s", pycurl.version)
84 8d0a4f99 Michael Hanselmann
85 33231500 Michael Hanselmann
  pycurl.global_init(pycurl.GLOBAL_ALL)
86 4331f6cd Michael Hanselmann
87 4331f6cd Michael Hanselmann
88 4331f6cd Michael Hanselmann
def Shutdown():
89 4331f6cd Michael Hanselmann
  """Stops the module-global HTTP client manager.
90 4331f6cd Michael Hanselmann

91 33231500 Michael Hanselmann
  Must be called before quitting the program and while exactly one thread is
92 33231500 Michael Hanselmann
  running.
93 4331f6cd Michael Hanselmann

94 4331f6cd Michael Hanselmann
  """
95 33231500 Michael Hanselmann
  pycurl.global_cleanup()
96 33231500 Michael Hanselmann
97 33231500 Michael Hanselmann
98 33231500 Michael Hanselmann
def _ConfigRpcCurl(curl):
99 80ec9f96 Michael Hanselmann
  noded_cert = str(pathutils.NODED_CERT_FILE)
100 4331f6cd Michael Hanselmann
101 33231500 Michael Hanselmann
  curl.setopt(pycurl.FOLLOWLOCATION, False)
102 33231500 Michael Hanselmann
  curl.setopt(pycurl.CAINFO, noded_cert)
103 33231500 Michael Hanselmann
  curl.setopt(pycurl.SSL_VERIFYHOST, 0)
104 33231500 Michael Hanselmann
  curl.setopt(pycurl.SSL_VERIFYPEER, True)
105 33231500 Michael Hanselmann
  curl.setopt(pycurl.SSLCERTTYPE, "PEM")
106 45f75526 Helga Velroyen
  curl.setopt(pycurl.SSLCERT, noded_cert)
107 33231500 Michael Hanselmann
  curl.setopt(pycurl.SSLKEYTYPE, "PEM")
108 45f75526 Helga Velroyen
  curl.setopt(pycurl.SSLKEY, noded_cert)
109 2ff587d4 Agata Murawska
  curl.setopt(pycurl.CONNECTTIMEOUT, constants.RPC_CONNECT_TIMEOUT)
110 33231500 Michael Hanselmann
111 33231500 Michael Hanselmann
112 e0e916fe Iustin Pop
def RunWithRPC(fn):
113 e0e916fe Iustin Pop
  """RPC-wrapper decorator.
114 e0e916fe Iustin Pop

115 e0e916fe Iustin Pop
  When applied to a function, it runs it with the RPC system
116 e0e916fe Iustin Pop
  initialized, and it shutsdown the system afterwards. This means the
117 e0e916fe Iustin Pop
  function must be called without RPC being initialized.
118 e0e916fe Iustin Pop

119 e0e916fe Iustin Pop
  """
120 e0e916fe Iustin Pop
  def wrapper(*args, **kwargs):
121 e0e916fe Iustin Pop
    Init()
122 e0e916fe Iustin Pop
    try:
123 e0e916fe Iustin Pop
      return fn(*args, **kwargs)
124 e0e916fe Iustin Pop
    finally:
125 e0e916fe Iustin Pop
      Shutdown()
126 e0e916fe Iustin Pop
  return wrapper
127 e0e916fe Iustin Pop
128 e0e916fe Iustin Pop
129 0c3d9c7c Thomas Thrainer
def _Compress(_, data):
130 30474135 Michael Hanselmann
  """Compresses a string for transport over RPC.
131 30474135 Michael Hanselmann

132 30474135 Michael Hanselmann
  Small amounts of data are not compressed.
133 30474135 Michael Hanselmann

134 30474135 Michael Hanselmann
  @type data: str
135 30474135 Michael Hanselmann
  @param data: Data
136 30474135 Michael Hanselmann
  @rtype: tuple
137 30474135 Michael Hanselmann
  @return: Encoded data to send
138 30474135 Michael Hanselmann

139 30474135 Michael Hanselmann
  """
140 30474135 Michael Hanselmann
  # Small amounts of data are not compressed
141 30474135 Michael Hanselmann
  if len(data) < 512:
142 30474135 Michael Hanselmann
    return (constants.RPC_ENCODING_NONE, data)
143 30474135 Michael Hanselmann
144 30474135 Michael Hanselmann
  # Compress with zlib and encode in base64
145 30474135 Michael Hanselmann
  return (constants.RPC_ENCODING_ZLIB_BASE64,
146 30474135 Michael Hanselmann
          base64.b64encode(zlib.compress(data, 3)))
147 30474135 Michael Hanselmann
148 30474135 Michael Hanselmann
149 781de953 Iustin Pop
class RpcResult(object):
150 781de953 Iustin Pop
  """RPC Result class.
151 781de953 Iustin Pop

152 781de953 Iustin Pop
  This class holds an RPC result. It is needed since in multi-node
153 05325a35 Bernardo Dal Seno
  calls we can't raise an exception just because one out of many
154 781de953 Iustin Pop
  failed, and therefore we use this class to encapsulate the result.
155 781de953 Iustin Pop

156 5bbd3f7f Michael Hanselmann
  @ivar data: the data payload, for successful results, or None
157 ed83f5cc Iustin Pop
  @ivar call: the name of the RPC call
158 ed83f5cc Iustin Pop
  @ivar node: the name of the node to which we made the call
159 ed83f5cc Iustin Pop
  @ivar offline: whether the operation failed because the node was
160 ed83f5cc Iustin Pop
      offline, as opposed to actual failure; offline=True will always
161 ed83f5cc Iustin Pop
      imply failed=True, in order to allow simpler checking if
162 ed83f5cc Iustin Pop
      the user doesn't care about the exact failure mode
163 4c4e4e1e Iustin Pop
  @ivar fail_msg: the error message if the call failed
164 ed83f5cc Iustin Pop

165 781de953 Iustin Pop
  """
166 ed83f5cc Iustin Pop
  def __init__(self, data=None, failed=False, offline=False,
167 ed83f5cc Iustin Pop
               call=None, node=None):
168 ed83f5cc Iustin Pop
    self.offline = offline
169 ed83f5cc Iustin Pop
    self.call = call
170 ed83f5cc Iustin Pop
    self.node = node
171 1645d22d Michael Hanselmann
172 ed83f5cc Iustin Pop
    if offline:
173 4c4e4e1e Iustin Pop
      self.fail_msg = "Node is marked offline"
174 f2def43a Iustin Pop
      self.data = self.payload = None
175 ed83f5cc Iustin Pop
    elif failed:
176 4c4e4e1e Iustin Pop
      self.fail_msg = self._EnsureErr(data)
177 f2def43a Iustin Pop
      self.data = self.payload = None
178 781de953 Iustin Pop
    else:
179 781de953 Iustin Pop
      self.data = data
180 d3c8b360 Iustin Pop
      if not isinstance(self.data, (tuple, list)):
181 4c4e4e1e Iustin Pop
        self.fail_msg = ("RPC layer error: invalid result type (%s)" %
182 4c4e4e1e Iustin Pop
                         type(self.data))
183 1645d22d Michael Hanselmann
        self.payload = None
184 d3c8b360 Iustin Pop
      elif len(data) != 2:
185 4c4e4e1e Iustin Pop
        self.fail_msg = ("RPC layer error: invalid result length (%d), "
186 4c4e4e1e Iustin Pop
                         "expected 2" % len(self.data))
187 1645d22d Michael Hanselmann
        self.payload = None
188 d3c8b360 Iustin Pop
      elif not self.data[0]:
189 4c4e4e1e Iustin Pop
        self.fail_msg = self._EnsureErr(self.data[1])
190 1645d22d Michael Hanselmann
        self.payload = None
191 f2def43a Iustin Pop
      else:
192 d3c8b360 Iustin Pop
        # finally success
193 4c4e4e1e Iustin Pop
        self.fail_msg = None
194 d3c8b360 Iustin Pop
        self.payload = data[1]
195 d3c8b360 Iustin Pop
196 2c0f74f2 Iustin Pop
    for attr_name in ["call", "data", "fail_msg",
197 2c0f74f2 Iustin Pop
                      "node", "offline", "payload"]:
198 2c0f74f2 Iustin Pop
      assert hasattr(self, attr_name), "Missing attribute %s" % attr_name
199 1645d22d Michael Hanselmann
200 47c477c8 Petr Pudlak
  def __repr__(self):
201 47c477c8 Petr Pudlak
    return ("RpcResult(data=%s, call=%s, node=%s, offline=%s, fail_msg=%s)" %
202 47c477c8 Petr Pudlak
            (self.offline, self.call, self.node, self.offline, self.fail_msg))
203 47c477c8 Petr Pudlak
204 d3c8b360 Iustin Pop
  @staticmethod
205 d3c8b360 Iustin Pop
  def _EnsureErr(val):
206 d3c8b360 Iustin Pop
    """Helper to ensure we return a 'True' value for error."""
207 d3c8b360 Iustin Pop
    if val:
208 d3c8b360 Iustin Pop
      return val
209 d3c8b360 Iustin Pop
    else:
210 d3c8b360 Iustin Pop
      return "No error information"
211 781de953 Iustin Pop
212 045dd6d9 Iustin Pop
  def Raise(self, msg, prereq=False, ecode=None):
213 781de953 Iustin Pop
    """If the result has failed, raise an OpExecError.
214 781de953 Iustin Pop

215 781de953 Iustin Pop
    This is used so that LU code doesn't have to check for each
216 781de953 Iustin Pop
    result, but instead can call this function.
217 781de953 Iustin Pop

218 781de953 Iustin Pop
    """
219 4c4e4e1e Iustin Pop
    if not self.fail_msg:
220 4c4e4e1e Iustin Pop
      return
221 4c4e4e1e Iustin Pop
222 4c4e4e1e Iustin Pop
    if not msg: # one could pass None for default message
223 4c4e4e1e Iustin Pop
      msg = ("Call '%s' to node '%s' has failed: %s" %
224 4c4e4e1e Iustin Pop
             (self.call, self.node, self.fail_msg))
225 4c4e4e1e Iustin Pop
    else:
226 4c4e4e1e Iustin Pop
      msg = "%s: %s" % (msg, self.fail_msg)
227 4c4e4e1e Iustin Pop
    if prereq:
228 4c4e4e1e Iustin Pop
      ec = errors.OpPrereqError
229 4c4e4e1e Iustin Pop
    else:
230 4c4e4e1e Iustin Pop
      ec = errors.OpExecError
231 045dd6d9 Iustin Pop
    if ecode is not None:
232 27137e55 Iustin Pop
      args = (msg, ecode)
233 045dd6d9 Iustin Pop
    else:
234 045dd6d9 Iustin Pop
      args = (msg, )
235 b459a848 Andrea Spadaccini
    raise ec(*args) # pylint: disable=W0142
236 781de953 Iustin Pop
237 95e7e85e Klaus Aehlig
  def Warn(self, msg, feedback_fn):
238 95e7e85e Klaus Aehlig
    """If the result has failed, call the feedback_fn.
239 95e7e85e Klaus Aehlig

240 95e7e85e Klaus Aehlig
    This is used to in cases were LU wants to warn the
241 95e7e85e Klaus Aehlig
    user about a failure, but continue anyway.
242 95e7e85e Klaus Aehlig

243 95e7e85e Klaus Aehlig
    """
244 95e7e85e Klaus Aehlig
    if not self.fail_msg:
245 95e7e85e Klaus Aehlig
      return
246 95e7e85e Klaus Aehlig
247 95e7e85e Klaus Aehlig
    msg = "%s: %s" % (msg, self.fail_msg)
248 95e7e85e Klaus Aehlig
    feedback_fn(msg)
249 95e7e85e Klaus Aehlig
250 781de953 Iustin Pop
251 bd6d1202 René Nussbaumer
def _SsconfResolver(ssconf_ips, node_list, _,
252 00267bfe Michael Hanselmann
                    ssc=ssconf.SimpleStore,
253 00267bfe Michael Hanselmann
                    nslookup_fn=netutils.Hostname.GetIP):
254 eb202c13 Manuel Franceschini
  """Return addresses for given node names.
255 eb202c13 Manuel Franceschini

256 bd6d1202 René Nussbaumer
  @type ssconf_ips: bool
257 bd6d1202 René Nussbaumer
  @param ssconf_ips: Use the ssconf IPs
258 eb202c13 Manuel Franceschini
  @type node_list: list
259 eb202c13 Manuel Franceschini
  @param node_list: List of node names
260 eb202c13 Manuel Franceschini
  @type ssc: class
261 eb202c13 Manuel Franceschini
  @param ssc: SimpleStore class that is used to obtain node->ip mappings
262 17f7fd27 Manuel Franceschini
  @type nslookup_fn: callable
263 17f7fd27 Manuel Franceschini
  @param nslookup_fn: function use to do NS lookup
264 00267bfe Michael Hanselmann
  @rtype: list of tuple; (string, string)
265 00267bfe Michael Hanselmann
  @return: List of tuples containing node name and IP address
266 eb202c13 Manuel Franceschini

267 eb202c13 Manuel Franceschini
  """
268 b43dcc5a Manuel Franceschini
  ss = ssc()
269 b43dcc5a Manuel Franceschini
  family = ss.GetPrimaryIPFamily()
270 bd6d1202 René Nussbaumer
271 bd6d1202 René Nussbaumer
  if ssconf_ips:
272 bd6d1202 René Nussbaumer
    iplist = ss.GetNodePrimaryIPList()
273 bd6d1202 René Nussbaumer
    ipmap = dict(entry.split() for entry in iplist)
274 bd6d1202 René Nussbaumer
  else:
275 bd6d1202 René Nussbaumer
    ipmap = {}
276 00267bfe Michael Hanselmann
277 00267bfe Michael Hanselmann
  result = []
278 b705c7a6 Manuel Franceschini
  for node in node_list:
279 00267bfe Michael Hanselmann
    ip = ipmap.get(node)
280 00267bfe Michael Hanselmann
    if ip is None:
281 00267bfe Michael Hanselmann
      ip = nslookup_fn(node, family=family)
282 1c3231aa Thomas Thrainer
    result.append((node, ip, node))
283 00267bfe Michael Hanselmann
284 00267bfe Michael Hanselmann
  return result
285 00267bfe Michael Hanselmann
286 00267bfe Michael Hanselmann
287 00267bfe Michael Hanselmann
class _StaticResolver:
288 00267bfe Michael Hanselmann
  def __init__(self, addresses):
289 00267bfe Michael Hanselmann
    """Initializes this class.
290 00267bfe Michael Hanselmann

291 00267bfe Michael Hanselmann
    """
292 00267bfe Michael Hanselmann
    self._addresses = addresses
293 00267bfe Michael Hanselmann
294 fce5efd1 Michael Hanselmann
  def __call__(self, hosts, _):
295 00267bfe Michael Hanselmann
    """Returns static addresses for hosts.
296 00267bfe Michael Hanselmann

297 00267bfe Michael Hanselmann
    """
298 00267bfe Michael Hanselmann
    assert len(hosts) == len(self._addresses)
299 1c3231aa Thomas Thrainer
    return zip(hosts, self._addresses, hosts)
300 00267bfe Michael Hanselmann
301 eb202c13 Manuel Franceschini
302 1c3231aa Thomas Thrainer
def _CheckConfigNode(node_uuid_or_name, node, accept_offline_node):
303 00267bfe Michael Hanselmann
  """Checks if a node is online.
304 eb202c13 Manuel Franceschini

305 1c3231aa Thomas Thrainer
  @type node_uuid_or_name: string
306 1c3231aa Thomas Thrainer
  @param node_uuid_or_name: Node UUID
307 00267bfe Michael Hanselmann
  @type node: L{objects.Node} or None
308 00267bfe Michael Hanselmann
  @param node: Node object
309 eb202c13 Manuel Franceschini

310 00267bfe Michael Hanselmann
  """
311 00267bfe Michael Hanselmann
  if node is None:
312 1c3231aa Thomas Thrainer
    # Assume that the passed parameter was actually a node name, so depend on
313 1c3231aa Thomas Thrainer
    # DNS for name resolution
314 1c3231aa Thomas Thrainer
    return (node_uuid_or_name, node_uuid_or_name, node_uuid_or_name)
315 00267bfe Michael Hanselmann
  else:
316 1c3231aa Thomas Thrainer
    if node.offline and not accept_offline_node:
317 1c3231aa Thomas Thrainer
      ip = _OFFLINE
318 1c3231aa Thomas Thrainer
    else:
319 1c3231aa Thomas Thrainer
      ip = node.primary_ip
320 1c3231aa Thomas Thrainer
    return (node.name, ip, node_uuid_or_name)
321 a8083063 Iustin Pop
322 a8083063 Iustin Pop
323 1c3231aa Thomas Thrainer
def _NodeConfigResolver(single_node_fn, all_nodes_fn, node_uuids, opts):
324 00267bfe Michael Hanselmann
  """Calculate node addresses using configuration.
325 a8083063 Iustin Pop

326 1c3231aa Thomas Thrainer
  Note that strings in node_uuids are treated as node names if the UUID is not
327 1c3231aa Thomas Thrainer
  found in the configuration.
328 1c3231aa Thomas Thrainer

329 a8083063 Iustin Pop
  """
330 890ea4ce Michael Hanselmann
  accept_offline_node = (opts is rpc_defs.ACCEPT_OFFLINE_NODE)
331 890ea4ce Michael Hanselmann
332 890ea4ce Michael Hanselmann
  assert accept_offline_node or opts is None, "Unknown option"
333 890ea4ce Michael Hanselmann
334 00267bfe Michael Hanselmann
  # Special case for single-host lookups
335 1c3231aa Thomas Thrainer
  if len(node_uuids) == 1:
336 1c3231aa Thomas Thrainer
    (uuid, ) = node_uuids
337 1c3231aa Thomas Thrainer
    return [_CheckConfigNode(uuid, single_node_fn(uuid), accept_offline_node)]
338 00267bfe Michael Hanselmann
  else:
339 00267bfe Michael Hanselmann
    all_nodes = all_nodes_fn()
340 1c3231aa Thomas Thrainer
    return [_CheckConfigNode(uuid, all_nodes.get(uuid, None),
341 890ea4ce Michael Hanselmann
                             accept_offline_node)
342 1c3231aa Thomas Thrainer
            for uuid in node_uuids]
343 00267bfe Michael Hanselmann
344 00267bfe Michael Hanselmann
345 00267bfe Michael Hanselmann
class _RpcProcessor:
346 aea5caef Michael Hanselmann
  def __init__(self, resolver, port, lock_monitor_cb=None):
347 00267bfe Michael Hanselmann
    """Initializes this class.
348 00267bfe Michael Hanselmann

349 1c3231aa Thomas Thrainer
    @param resolver: callable accepting a list of node UUIDs or hostnames,
350 1c3231aa Thomas Thrainer
      returning a list of tuples containing name, IP address and original name
351 1c3231aa Thomas Thrainer
      of the resolved node. IP address can be the name or the special value
352 1c3231aa Thomas Thrainer
      L{_OFFLINE} to mark offline machines.
353 00267bfe Michael Hanselmann
    @type port: int
354 00267bfe Michael Hanselmann
    @param port: TCP port
355 aea5caef Michael Hanselmann
    @param lock_monitor_cb: Callable for registering with lock monitor
356 3ef3c771 Iustin Pop

357 a8083063 Iustin Pop
    """
358 00267bfe Michael Hanselmann
    self._resolver = resolver
359 00267bfe Michael Hanselmann
    self._port = port
360 aea5caef Michael Hanselmann
    self._lock_monitor_cb = lock_monitor_cb
361 eb202c13 Manuel Franceschini
362 00267bfe Michael Hanselmann
  @staticmethod
363 00267bfe Michael Hanselmann
  def _PrepareRequests(hosts, port, procedure, body, read_timeout):
364 00267bfe Michael Hanselmann
    """Prepares requests by sorting offline hosts into separate list.
365 eb202c13 Manuel Franceschini

366 d9de612c Iustin Pop
    @type body: dict
367 d9de612c Iustin Pop
    @param body: a dictionary with per-host body data
368 d9de612c Iustin Pop

369 00267bfe Michael Hanselmann
    """
370 00267bfe Michael Hanselmann
    results = {}
371 00267bfe Michael Hanselmann
    requests = {}
372 bdf7d8c0 Iustin Pop
373 d9de612c Iustin Pop
    assert isinstance(body, dict)
374 d9de612c Iustin Pop
    assert len(body) == len(hosts)
375 d9de612c Iustin Pop
    assert compat.all(isinstance(v, str) for v in body.values())
376 1c3231aa Thomas Thrainer
    assert frozenset(map(lambda x: x[2], hosts)) == frozenset(body.keys()), \
377 d9de612c Iustin Pop
        "%s != %s" % (hosts, body.keys())
378 d9de612c Iustin Pop
379 1c3231aa Thomas Thrainer
    for (name, ip, original_name) in hosts:
380 00267bfe Michael Hanselmann
      if ip is _OFFLINE:
381 00267bfe Michael Hanselmann
        # Node is marked as offline
382 1c3231aa Thomas Thrainer
        results[original_name] = RpcResult(node=name,
383 1c3231aa Thomas Thrainer
                                           offline=True,
384 1c3231aa Thomas Thrainer
                                           call=procedure)
385 00267bfe Michael Hanselmann
      else:
386 1c3231aa Thomas Thrainer
        requests[original_name] = \
387 00267bfe Michael Hanselmann
          http.client.HttpClientRequest(str(ip), port,
388 7530364d Iustin Pop
                                        http.HTTP_POST, str("/%s" % procedure),
389 00267bfe Michael Hanselmann
                                        headers=_RPC_CLIENT_HEADERS,
390 1c3231aa Thomas Thrainer
                                        post_data=body[original_name],
391 7cb2d205 Michael Hanselmann
                                        read_timeout=read_timeout,
392 abbf2cd9 Michael Hanselmann
                                        nicename="%s/%s" % (name, procedure),
393 abbf2cd9 Michael Hanselmann
                                        curl_config_fn=_ConfigRpcCurl)
394 a8083063 Iustin Pop
395 00267bfe Michael Hanselmann
    return (results, requests)
396 00267bfe Michael Hanselmann
397 00267bfe Michael Hanselmann
  @staticmethod
398 00267bfe Michael Hanselmann
  def _CombineResults(results, requests, procedure):
399 00267bfe Michael Hanselmann
    """Combines pre-computed results for offline hosts with actual call results.
400 bdf7d8c0 Iustin Pop

401 a8083063 Iustin Pop
    """
402 00267bfe Michael Hanselmann
    for name, req in requests.items():
403 00267bfe Michael Hanselmann
      if req.success and req.resp_status_code == http.HTTP_OK:
404 00267bfe Michael Hanselmann
        host_result = RpcResult(data=serializer.LoadJson(req.resp_body),
405 00267bfe Michael Hanselmann
                                node=name, call=procedure)
406 00267bfe Michael Hanselmann
      else:
407 00267bfe Michael Hanselmann
        # TODO: Better error reporting
408 00267bfe Michael Hanselmann
        if req.error:
409 00267bfe Michael Hanselmann
          msg = req.error
410 00267bfe Michael Hanselmann
        else:
411 00267bfe Michael Hanselmann
          msg = req.resp_body
412 eb202c13 Manuel Franceschini
413 00267bfe Michael Hanselmann
        logging.error("RPC error in %s on node %s: %s", procedure, name, msg)
414 00267bfe Michael Hanselmann
        host_result = RpcResult(data=msg, failed=True, node=name,
415 00267bfe Michael Hanselmann
                                call=procedure)
416 ecfe9491 Michael Hanselmann
417 00267bfe Michael Hanselmann
      results[name] = host_result
418 92fd2250 Iustin Pop
419 00267bfe Michael Hanselmann
    return results
420 a8083063 Iustin Pop
421 1c3231aa Thomas Thrainer
  def __call__(self, nodes, procedure, body, read_timeout, resolver_opts,
422 065be3f0 Michael Hanselmann
               _req_process_fn=None):
423 00267bfe Michael Hanselmann
    """Makes an RPC request to a number of nodes.
424 ecfe9491 Michael Hanselmann

425 1c3231aa Thomas Thrainer
    @type nodes: sequence
426 1c3231aa Thomas Thrainer
    @param nodes: node UUIDs or Hostnames
427 00267bfe Michael Hanselmann
    @type procedure: string
428 00267bfe Michael Hanselmann
    @param procedure: Request path
429 d9de612c Iustin Pop
    @type body: dictionary
430 d9de612c Iustin Pop
    @param body: dictionary with request bodies per host
431 00267bfe Michael Hanselmann
    @type read_timeout: int or None
432 00267bfe Michael Hanselmann
    @param read_timeout: Read timeout for request
433 05325a35 Bernardo Dal Seno
    @rtype: dictionary
434 05325a35 Bernardo Dal Seno
    @return: a dictionary mapping host names to rpc.RpcResult objects
435 a8083063 Iustin Pop

436 a8083063 Iustin Pop
    """
437 83e7af18 Michael Hanselmann
    assert read_timeout is not None, \
438 83e7af18 Michael Hanselmann
      "Missing RPC read timeout for procedure '%s'" % procedure
439 a8083063 Iustin Pop
440 065be3f0 Michael Hanselmann
    if _req_process_fn is None:
441 065be3f0 Michael Hanselmann
      _req_process_fn = http.client.ProcessRequests
442 065be3f0 Michael Hanselmann
443 00267bfe Michael Hanselmann
    (results, requests) = \
444 1c3231aa Thomas Thrainer
      self._PrepareRequests(self._resolver(nodes, resolver_opts), self._port,
445 fce5efd1 Michael Hanselmann
                            procedure, body, read_timeout)
446 a8083063 Iustin Pop
447 abbf2cd9 Michael Hanselmann
    _req_process_fn(requests.values(), lock_monitor_cb=self._lock_monitor_cb)
448 a8083063 Iustin Pop
449 00267bfe Michael Hanselmann
    assert not frozenset(results).intersection(requests)
450 ecfe9491 Michael Hanselmann
451 00267bfe Michael Hanselmann
    return self._CombineResults(results, requests, procedure)
452 a8083063 Iustin Pop
453 a8083063 Iustin Pop
454 cd40dc53 Michael Hanselmann
class _RpcClientBase:
455 065be3f0 Michael Hanselmann
  def __init__(self, resolver, encoder_fn, lock_monitor_cb=None,
456 065be3f0 Michael Hanselmann
               _req_process_fn=None):
457 cd40dc53 Michael Hanselmann
    """Initializes this class.
458 cd40dc53 Michael Hanselmann

459 cd40dc53 Michael Hanselmann
    """
460 065be3f0 Michael Hanselmann
    proc = _RpcProcessor(resolver,
461 065be3f0 Michael Hanselmann
                         netutils.GetDaemonPort(constants.NODED),
462 065be3f0 Michael Hanselmann
                         lock_monitor_cb=lock_monitor_cb)
463 065be3f0 Michael Hanselmann
    self._proc = compat.partial(proc, _req_process_fn=_req_process_fn)
464 cd40dc53 Michael Hanselmann
    self._encoder = compat.partial(self._EncodeArg, encoder_fn)
465 cd40dc53 Michael Hanselmann
466 cd40dc53 Michael Hanselmann
  @staticmethod
467 0c3d9c7c Thomas Thrainer
  def _EncodeArg(encoder_fn, node, (argkind, value)):
468 cd40dc53 Michael Hanselmann
    """Encode argument.
469 cd40dc53 Michael Hanselmann

470 cd40dc53 Michael Hanselmann
    """
471 cd40dc53 Michael Hanselmann
    if argkind is None:
472 cd40dc53 Michael Hanselmann
      return value
473 cd40dc53 Michael Hanselmann
    else:
474 0c3d9c7c Thomas Thrainer
      return encoder_fn(argkind)(node, value)
475 cd40dc53 Michael Hanselmann
476 f7d9b3aa Michael Hanselmann
  def _Call(self, cdef, node_list, args):
477 cd40dc53 Michael Hanselmann
    """Entry point for automatically generated RPC wrappers.
478 cd40dc53 Michael Hanselmann

479 cd40dc53 Michael Hanselmann
    """
480 dd6d2d09 Michael Hanselmann
    (procedure, _, resolver_opts, timeout, argdefs,
481 dd6d2d09 Michael Hanselmann
     prep_fn, postproc_fn, _) = cdef
482 f7d9b3aa Michael Hanselmann
483 f7d9b3aa Michael Hanselmann
    if callable(timeout):
484 f7d9b3aa Michael Hanselmann
      read_timeout = timeout(args)
485 f7d9b3aa Michael Hanselmann
    else:
486 f7d9b3aa Michael Hanselmann
      read_timeout = timeout
487 cd40dc53 Michael Hanselmann
488 dd6d2d09 Michael Hanselmann
    if callable(resolver_opts):
489 dd6d2d09 Michael Hanselmann
      req_resolver_opts = resolver_opts(args)
490 dd6d2d09 Michael Hanselmann
    else:
491 dd6d2d09 Michael Hanselmann
      req_resolver_opts = resolver_opts
492 dd6d2d09 Michael Hanselmann
493 e78667fe Michael Hanselmann
    if len(args) != len(argdefs):
494 e78667fe Michael Hanselmann
      raise errors.ProgrammerError("Number of passed arguments doesn't match")
495 e78667fe Michael Hanselmann
496 d9de612c Iustin Pop
    if prep_fn is None:
497 0c3d9c7c Thomas Thrainer
      prep_fn = lambda _, args: args
498 0c3d9c7c Thomas Thrainer
    assert callable(prep_fn)
499 0c3d9c7c Thomas Thrainer
500 0c3d9c7c Thomas Thrainer
    # encode the arguments for each node individually, pass them and the node
501 0c3d9c7c Thomas Thrainer
    # name to the prep_fn, and serialise its return value
502 0c3d9c7c Thomas Thrainer
    encode_args_fn = lambda node: map(compat.partial(self._encoder, node),
503 0c3d9c7c Thomas Thrainer
                                      zip(map(compat.snd, argdefs), args))
504 1a182390 Santi Raffa
    pnbody = dict(
505 1a182390 Santi Raffa
      (n,
506 1a182390 Santi Raffa
       serializer.DumpJson(prep_fn(n, encode_args_fn(n)),
507 1a182390 Santi Raffa
                           private_encoder=serializer.EncodeWithPrivateFields))
508 1a182390 Santi Raffa
      for n in node_list
509 1a182390 Santi Raffa
    )
510 d9de612c Iustin Pop
511 fce5efd1 Michael Hanselmann
    result = self._proc(node_list, procedure, pnbody, read_timeout,
512 fce5efd1 Michael Hanselmann
                        req_resolver_opts)
513 26d502d0 Michael Hanselmann
514 26d502d0 Michael Hanselmann
    if postproc_fn:
515 d9da5065 Michael Hanselmann
      return dict(map(lambda (key, value): (key, postproc_fn(value)),
516 d9da5065 Michael Hanselmann
                      result.items()))
517 26d502d0 Michael Hanselmann
    else:
518 26d502d0 Michael Hanselmann
      return result
519 cd40dc53 Michael Hanselmann
520 cd40dc53 Michael Hanselmann
521 0c3d9c7c Thomas Thrainer
def _ObjectToDict(_, value):
522 cd40dc53 Michael Hanselmann
  """Converts an object to a dictionary.
523 cd40dc53 Michael Hanselmann

524 cd40dc53 Michael Hanselmann
  @note: See L{objects}.
525 cd40dc53 Michael Hanselmann

526 cd40dc53 Michael Hanselmann
  """
527 cd40dc53 Michael Hanselmann
  return value.ToDict()
528 cd40dc53 Michael Hanselmann
529 cd40dc53 Michael Hanselmann
530 0c3d9c7c Thomas Thrainer
def _ObjectListToDict(node, value):
531 cd40dc53 Michael Hanselmann
  """Converts a list of L{objects} to dictionaries.
532 cd40dc53 Michael Hanselmann

533 cd40dc53 Michael Hanselmann
  """
534 0c3d9c7c Thomas Thrainer
  return map(compat.partial(_ObjectToDict, node), value)
535 cd40dc53 Michael Hanselmann
536 cd40dc53 Michael Hanselmann
537 0c3d9c7c Thomas Thrainer
def _PrepareFileUpload(getents_fn, node, filename):
538 cd40dc53 Michael Hanselmann
  """Loads a file and prepares it for an upload to nodes.
539 cd40dc53 Michael Hanselmann

540 cd40dc53 Michael Hanselmann
  """
541 2ce40421 Michael Hanselmann
  statcb = utils.FileStatHelper()
542 0c3d9c7c Thomas Thrainer
  data = _Compress(node, utils.ReadFile(filename, preread=statcb))
543 2ce40421 Michael Hanselmann
  st = statcb.st
544 601dfcbb Michael Hanselmann
545 601dfcbb Michael Hanselmann
  if getents_fn is None:
546 601dfcbb Michael Hanselmann
    getents_fn = runtime.GetEnts
547 601dfcbb Michael Hanselmann
548 601dfcbb Michael Hanselmann
  getents = getents_fn()
549 601dfcbb Michael Hanselmann
550 cffbbae7 Michael Hanselmann
  virt_filename = vcluster.MakeVirtualPath(filename)
551 cffbbae7 Michael Hanselmann
552 cffbbae7 Michael Hanselmann
  return [virt_filename, data, st.st_mode, getents.LookupUid(st.st_uid),
553 cd40dc53 Michael Hanselmann
          getents.LookupGid(st.st_gid), st.st_atime, st.st_mtime]
554 cd40dc53 Michael Hanselmann
555 cd40dc53 Michael Hanselmann
556 0c3d9c7c Thomas Thrainer
def _PrepareFinalizeExportDisks(_, snap_disks):
557 cd40dc53 Michael Hanselmann
  """Encodes disks for finalizing export.
558 cd40dc53 Michael Hanselmann

559 cd40dc53 Michael Hanselmann
  """
560 cd40dc53 Michael Hanselmann
  flat_disks = []
561 cd40dc53 Michael Hanselmann
562 cd40dc53 Michael Hanselmann
  for disk in snap_disks:
563 cd40dc53 Michael Hanselmann
    if isinstance(disk, bool):
564 cd40dc53 Michael Hanselmann
      flat_disks.append(disk)
565 cd40dc53 Michael Hanselmann
    else:
566 cd40dc53 Michael Hanselmann
      flat_disks.append(disk.ToDict())
567 cd40dc53 Michael Hanselmann
568 cd40dc53 Michael Hanselmann
  return flat_disks
569 cd40dc53 Michael Hanselmann
570 cd40dc53 Michael Hanselmann
571 0c3d9c7c Thomas Thrainer
def _EncodeBlockdevRename(_, value):
572 cd40dc53 Michael Hanselmann
  """Encodes information for renaming block devices.
573 cd40dc53 Michael Hanselmann

574 cd40dc53 Michael Hanselmann
  """
575 cd40dc53 Michael Hanselmann
  return [(d.ToDict(), uid) for d, uid in value]
576 cd40dc53 Michael Hanselmann
577 cd40dc53 Michael Hanselmann
578 32389d91 Helga Velroyen
def _AddSpindlesToLegacyNodeInfo(result, space_info):
579 32389d91 Helga Velroyen
  """Extracts the spindle information from the space info and adds
580 32389d91 Helga Velroyen
  it to the result dictionary.
581 32389d91 Helga Velroyen

582 32389d91 Helga Velroyen
  @type result: dict of strings
583 32389d91 Helga Velroyen
  @param result: dictionary holding the result of the legacy node info
584 32389d91 Helga Velroyen
  @type space_info: list of dicts of strings
585 32389d91 Helga Velroyen
  @param space_info: list, each row holding space information of one storage
586 32389d91 Helga Velroyen
    unit
587 32389d91 Helga Velroyen
  @rtype: None
588 32389d91 Helga Velroyen
  @return: does not return anything, manipulates the C{result} variable
589 32389d91 Helga Velroyen

590 32389d91 Helga Velroyen
  """
591 32389d91 Helga Velroyen
  lvm_pv_info = utils.storage.LookupSpaceInfoByStorageType(
592 32389d91 Helga Velroyen
      space_info, constants.ST_LVM_PV)
593 32389d91 Helga Velroyen
  if lvm_pv_info:
594 32389d91 Helga Velroyen
    result["spindles_free"] = lvm_pv_info["storage_free"]
595 32389d91 Helga Velroyen
    result["spindles_total"] = lvm_pv_info["storage_size"]
596 20faaa74 Helga Velroyen
  else:
597 6c00b2c7 Helga Velroyen
    result["spindles_free"] = 0
598 6c00b2c7 Helga Velroyen
    result["spindles_total"] = 0
599 06fb92cf Bernardo Dal Seno
600 06fb92cf Bernardo Dal Seno
601 6c00b2c7 Helga Velroyen
def _AddStorageInfoToLegacyNodeInfoByTemplate(
602 6c00b2c7 Helga Velroyen
    result, space_info, disk_template):
603 6c00b2c7 Helga Velroyen
  """Extracts the storage space information of the disk template from
604 32389d91 Helga Velroyen
  the space info and adds it to the result dictionary.
605 32389d91 Helga Velroyen

606 32389d91 Helga Velroyen
  @see: C{_AddSpindlesToLegacyNodeInfo} for parameter information.
607 06fb92cf Bernardo Dal Seno

608 06fb92cf Bernardo Dal Seno
  """
609 6c00b2c7 Helga Velroyen
  if utils.storage.DiskTemplateSupportsSpaceReporting(disk_template):
610 6c00b2c7 Helga Velroyen
    disk_info = utils.storage.LookupSpaceInfoByDiskTemplate(
611 6c00b2c7 Helga Velroyen
        space_info, disk_template)
612 6c00b2c7 Helga Velroyen
    result["name"] = disk_info["name"]
613 6c00b2c7 Helga Velroyen
    result["storage_free"] = disk_info["storage_free"]
614 6c00b2c7 Helga Velroyen
    result["storage_size"] = disk_info["storage_size"]
615 06fb92cf Bernardo Dal Seno
  else:
616 6c00b2c7 Helga Velroyen
    # FIXME: consider displaying '-' in this case
617 6c00b2c7 Helga Velroyen
    result["storage_free"] = 0
618 6c00b2c7 Helga Velroyen
    result["storage_size"] = 0
619 06fb92cf Bernardo Dal Seno
620 06fb92cf Bernardo Dal Seno
621 6c00b2c7 Helga Velroyen
def MakeLegacyNodeInfo(data, disk_template):
622 4e745e62 Santi Raffa
  """Formats the data returned by call_node_info.
623 b112bfc4 René Nussbaumer

624 b112bfc4 René Nussbaumer
  Converts the data into a single dictionary. This is fine for most use cases,
625 b112bfc4 René Nussbaumer
  but some require information from more than one volume group or hypervisor.
626 b112bfc4 René Nussbaumer

627 b112bfc4 René Nussbaumer
  """
628 32389d91 Helga Velroyen
  (bootid, space_info, (hv_info, )) = data
629 91c17910 Iustin Pop
630 91c17910 Iustin Pop
  ret = utils.JoinDisjointDicts(hv_info, {"bootid": bootid})
631 91c17910 Iustin Pop
632 6c00b2c7 Helga Velroyen
  _AddSpindlesToLegacyNodeInfo(ret, space_info)
633 6c00b2c7 Helga Velroyen
  _AddStorageInfoToLegacyNodeInfoByTemplate(ret, space_info, disk_template)
634 b112bfc4 René Nussbaumer
635 91c17910 Iustin Pop
  return ret
636 b112bfc4 René Nussbaumer
637 b112bfc4 René Nussbaumer
638 cd46491f René Nussbaumer
def _AnnotateDParamsDRBD(disk, (drbd_params, data_params, meta_params)):
639 cd46491f René Nussbaumer
  """Annotates just DRBD disks layouts.
640 cd46491f René Nussbaumer

641 cd46491f René Nussbaumer
  """
642 cd3b4ff4 Helga Velroyen
  assert disk.dev_type == constants.DT_DRBD8
643 cd46491f René Nussbaumer
644 cd46491f René Nussbaumer
  disk.params = objects.FillDict(drbd_params, disk.params)
645 cd46491f René Nussbaumer
  (dev_data, dev_meta) = disk.children
646 cd46491f René Nussbaumer
  dev_data.params = objects.FillDict(data_params, dev_data.params)
647 cd46491f René Nussbaumer
  dev_meta.params = objects.FillDict(meta_params, dev_meta.params)
648 cd46491f René Nussbaumer
649 cd46491f René Nussbaumer
  return disk
650 cd46491f René Nussbaumer
651 cd46491f René Nussbaumer
652 cd46491f René Nussbaumer
def _AnnotateDParamsGeneric(disk, (params, )):
653 cd46491f René Nussbaumer
  """Generic disk parameter annotation routine.
654 cd46491f René Nussbaumer

655 cd46491f René Nussbaumer
  """
656 cd3b4ff4 Helga Velroyen
  assert disk.dev_type != constants.DT_DRBD8
657 cd46491f René Nussbaumer
658 cd46491f René Nussbaumer
  disk.params = objects.FillDict(params, disk.params)
659 cd46491f René Nussbaumer
660 cd46491f René Nussbaumer
  return disk
661 cd46491f René Nussbaumer
662 cd46491f René Nussbaumer
663 0c3d9c7c Thomas Thrainer
def AnnotateDiskParams(disks, disk_params):
664 cd46491f René Nussbaumer
  """Annotates the disk objects with the disk parameters.
665 cd46491f René Nussbaumer

666 cd46491f René Nussbaumer
  @param disks: The list of disks objects to annotate
667 0c3d9c7c Thomas Thrainer
  @param disk_params: The disk parameters for annotation
668 cd46491f René Nussbaumer
  @returns: A list of disk objects annotated
669 cd46491f René Nussbaumer

670 cd46491f René Nussbaumer
  """
671 0c3d9c7c Thomas Thrainer
  def AnnotateDisk(disk):
672 0c3d9c7c Thomas Thrainer
    if disk.dev_type == constants.DT_DISKLESS:
673 0c3d9c7c Thomas Thrainer
      return disk
674 cd46491f René Nussbaumer
675 0c3d9c7c Thomas Thrainer
    ld_params = objects.Disk.ComputeLDParams(disk.dev_type, disk_params)
676 cd46491f René Nussbaumer
677 0c3d9c7c Thomas Thrainer
    if disk.dev_type == constants.DT_DRBD8:
678 0c3d9c7c Thomas Thrainer
      return _AnnotateDParamsDRBD(disk, ld_params)
679 0c3d9c7c Thomas Thrainer
    else:
680 0c3d9c7c Thomas Thrainer
      return _AnnotateDParamsGeneric(disk, ld_params)
681 0c3d9c7c Thomas Thrainer
682 0c3d9c7c Thomas Thrainer
  return [AnnotateDisk(disk.Copy()) for disk in disks]
683 cd46491f René Nussbaumer
684 cd46491f René Nussbaumer
685 da803ff1 Helga Velroyen
def _GetExclusiveStorageFlag(cfg, node_uuid):
686 1c3231aa Thomas Thrainer
  ni = cfg.GetNodeInfo(node_uuid)
687 319322a7 Bernardo Dal Seno
  if ni is None:
688 1c3231aa Thomas Thrainer
    raise errors.OpPrereqError("Invalid node name %s" % node_uuid,
689 319322a7 Bernardo Dal Seno
                               errors.ECODE_NOENT)
690 319322a7 Bernardo Dal Seno
  return cfg.GetNdParams(ni)[constants.ND_EXCLUSIVE_STORAGE]
691 319322a7 Bernardo Dal Seno
692 319322a7 Bernardo Dal Seno
693 da803ff1 Helga Velroyen
def _AddExclusiveStorageFlagToLvmStorageUnits(storage_units, es_flag):
694 da803ff1 Helga Velroyen
  """Adds the exclusive storage flag to lvm units.
695 da803ff1 Helga Velroyen

696 da803ff1 Helga Velroyen
  This function creates a copy of the storage_units lists, with the
697 da803ff1 Helga Velroyen
  es_flag being added to all lvm storage units.
698 da803ff1 Helga Velroyen

699 da803ff1 Helga Velroyen
  @type storage_units: list of pairs (string, string)
700 da803ff1 Helga Velroyen
  @param storage_units: list of 'raw' storage units, consisting only of
701 da803ff1 Helga Velroyen
    (storage_type, storage_key)
702 da803ff1 Helga Velroyen
  @type es_flag: boolean
703 da803ff1 Helga Velroyen
  @param es_flag: exclusive storage flag
704 da803ff1 Helga Velroyen
  @rtype: list of tuples (string, string, list)
705 da803ff1 Helga Velroyen
  @return: list of storage units (storage_type, storage_key, params) with
706 da803ff1 Helga Velroyen
    the params containing the es_flag for lvm-vg storage units
707 da803ff1 Helga Velroyen

708 da803ff1 Helga Velroyen
  """
709 da803ff1 Helga Velroyen
  result = []
710 da803ff1 Helga Velroyen
  for (storage_type, storage_key) in storage_units:
711 e7098533 Helga Velroyen
    if storage_type in [constants.ST_LVM_VG]:
712 52a8a6ae Helga Velroyen
      result.append((storage_type, storage_key, [es_flag]))
713 e7098533 Helga Velroyen
      if es_flag:
714 e7098533 Helga Velroyen
        result.append((constants.ST_LVM_PV, storage_key, [es_flag]))
715 da803ff1 Helga Velroyen
    else:
716 da803ff1 Helga Velroyen
      result.append((storage_type, storage_key, []))
717 da803ff1 Helga Velroyen
  return result
718 da803ff1 Helga Velroyen
719 da803ff1 Helga Velroyen
720 1c3231aa Thomas Thrainer
def GetExclusiveStorageForNodes(cfg, node_uuids):
721 319322a7 Bernardo Dal Seno
  """Return the exclusive storage flag for all the given nodes.
722 319322a7 Bernardo Dal Seno

723 319322a7 Bernardo Dal Seno
  @type cfg: L{config.ConfigWriter}
724 319322a7 Bernardo Dal Seno
  @param cfg: cluster configuration
725 1c3231aa Thomas Thrainer
  @type node_uuids: list or tuple
726 1c3231aa Thomas Thrainer
  @param node_uuids: node UUIDs for which to read the flag
727 319322a7 Bernardo Dal Seno
  @rtype: dict
728 da803ff1 Helga Velroyen
  @return: mapping from node uuids to exclusive storage flags
729 1c3231aa Thomas Thrainer
  @raise errors.OpPrereqError: if any given node name has no corresponding
730 1c3231aa Thomas Thrainer
  node
731 319322a7 Bernardo Dal Seno

732 319322a7 Bernardo Dal Seno
  """
733 da803ff1 Helga Velroyen
  getflag = lambda n: _GetExclusiveStorageFlag(cfg, n)
734 1c3231aa Thomas Thrainer
  flags = map(getflag, node_uuids)
735 1c3231aa Thomas Thrainer
  return dict(zip(node_uuids, flags))
736 319322a7 Bernardo Dal Seno
737 319322a7 Bernardo Dal Seno
738 da803ff1 Helga Velroyen
def PrepareStorageUnitsForNodes(cfg, storage_units, node_uuids):
739 da803ff1 Helga Velroyen
  """Return the lvm storage unit for all the given nodes.
740 da803ff1 Helga Velroyen

741 da803ff1 Helga Velroyen
  Main purpose of this function is to map the exclusive storage flag, which
742 da803ff1 Helga Velroyen
  can be different for each node, to the default LVM storage unit.
743 da803ff1 Helga Velroyen

744 da803ff1 Helga Velroyen
  @type cfg: L{config.ConfigWriter}
745 da803ff1 Helga Velroyen
  @param cfg: cluster configuration
746 da803ff1 Helga Velroyen
  @type storage_units: list of pairs (string, string)
747 da803ff1 Helga Velroyen
  @param storage_units: list of 'raw' storage units, e.g. pairs of
748 da803ff1 Helga Velroyen
    (storage_type, storage_key)
749 da803ff1 Helga Velroyen
  @type node_uuids: list or tuple
750 da803ff1 Helga Velroyen
  @param node_uuids: node UUIDs for which to read the flag
751 da803ff1 Helga Velroyen
  @rtype: dict
752 da803ff1 Helga Velroyen
  @return: mapping from node uuids to a list of storage units which include
753 da803ff1 Helga Velroyen
    the exclusive storage flag for lvm storage
754 da803ff1 Helga Velroyen
  @raise errors.OpPrereqError: if any given node name has no corresponding
755 da803ff1 Helga Velroyen
  node
756 da803ff1 Helga Velroyen

757 da803ff1 Helga Velroyen
  """
758 da803ff1 Helga Velroyen
  getunit = lambda n: _AddExclusiveStorageFlagToLvmStorageUnits(
759 da803ff1 Helga Velroyen
      storage_units, _GetExclusiveStorageFlag(cfg, n))
760 da803ff1 Helga Velroyen
  flags = map(getunit, node_uuids)
761 da803ff1 Helga Velroyen
  return dict(zip(node_uuids, flags))
762 da803ff1 Helga Velroyen
763 da803ff1 Helga Velroyen
764 cd40dc53 Michael Hanselmann
#: Generic encoders
765 cd40dc53 Michael Hanselmann
_ENCODERS = {
766 cd40dc53 Michael Hanselmann
  rpc_defs.ED_OBJECT_DICT: _ObjectToDict,
767 cd40dc53 Michael Hanselmann
  rpc_defs.ED_OBJECT_DICT_LIST: _ObjectListToDict,
768 cd40dc53 Michael Hanselmann
  rpc_defs.ED_COMPRESS: _Compress,
769 cd40dc53 Michael Hanselmann
  rpc_defs.ED_FINALIZE_EXPORT_DISKS: _PrepareFinalizeExportDisks,
770 cd40dc53 Michael Hanselmann
  rpc_defs.ED_BLOCKDEV_RENAME: _EncodeBlockdevRename,
771 cd40dc53 Michael Hanselmann
  }
772 cd40dc53 Michael Hanselmann
773 cd40dc53 Michael Hanselmann
774 cd40dc53 Michael Hanselmann
class RpcRunner(_RpcClientBase,
775 cd40dc53 Michael Hanselmann
                _generated_rpc.RpcClientDefault,
776 415a7304 Michael Hanselmann
                _generated_rpc.RpcClientBootstrap,
777 bd6d1202 René Nussbaumer
                _generated_rpc.RpcClientDnsOnly,
778 415a7304 Michael Hanselmann
                _generated_rpc.RpcClientConfig):
779 87b3cb26 Michael Hanselmann
  """RPC runner class.
780 a8083063 Iustin Pop

781 87b3cb26 Michael Hanselmann
  """
782 d5ea30e8 Michael Hanselmann
  def __init__(self, cfg, lock_monitor_cb, _req_process_fn=None, _getents=None):
783 87b3cb26 Michael Hanselmann
    """Initialized the RPC runner.
784 a8083063 Iustin Pop

785 d5ea30e8 Michael Hanselmann
    @type cfg: L{config.ConfigWriter}
786 d5ea30e8 Michael Hanselmann
    @param cfg: Configuration
787 d5ea30e8 Michael Hanselmann
    @type lock_monitor_cb: callable
788 d5ea30e8 Michael Hanselmann
    @param lock_monitor_cb: Lock monitor callback
789 a8083063 Iustin Pop

790 72737a7f Iustin Pop
    """
791 d5ea30e8 Michael Hanselmann
    self._cfg = cfg
792 cd40dc53 Michael Hanselmann
793 cd40dc53 Michael Hanselmann
    encoders = _ENCODERS.copy()
794 cd40dc53 Michael Hanselmann
795 cd40dc53 Michael Hanselmann
    encoders.update({
796 601dfcbb Michael Hanselmann
      # Encoders requiring configuration object
797 cd40dc53 Michael Hanselmann
      rpc_defs.ED_INST_DICT: self._InstDict,
798 5fce6a89 Constantinos Venetsanopoulos
      rpc_defs.ED_INST_DICT_HVP_BEP_DP: self._InstDictHvpBepDp,
799 b8291e00 René Nussbaumer
      rpc_defs.ED_INST_DICT_OSP_DP: self._InstDictOspDp,
800 cbe4a0a5 Dimitris Aragiorgis
      rpc_defs.ED_NIC_DICT: self._NicDict,
801 c5708931 Dimitris Aragiorgis
      rpc_defs.ED_DEVICE_DICT: self._DeviceDict,
802 601dfcbb Michael Hanselmann
803 aedf5fd7 René Nussbaumer
      # Encoders annotating disk parameters
804 aedf5fd7 René Nussbaumer
      rpc_defs.ED_DISKS_DICT_DP: self._DisksDictDP,
805 235a6b29 Thomas Thrainer
      rpc_defs.ED_MULTI_DISKS_DICT_DP: self._MultiDiskDictDP,
806 aedf5fd7 René Nussbaumer
      rpc_defs.ED_SINGLE_DISK_DICT_DP: self._SingleDiskDictDP,
807 0c3d9c7c Thomas Thrainer
      rpc_defs.ED_NODE_TO_DISK_DICT_DP: self._EncodeNodeToDiskDictDP,
808 aedf5fd7 René Nussbaumer
809 601dfcbb Michael Hanselmann
      # Encoders with special requirements
810 601dfcbb Michael Hanselmann
      rpc_defs.ED_FILE_DETAILS: compat.partial(_PrepareFileUpload, _getents),
811 0c3d9c7c Thomas Thrainer
812 0c3d9c7c Thomas Thrainer
      rpc_defs.ED_IMPEXP_IO: self._EncodeImportExportIO,
813 cd40dc53 Michael Hanselmann
      })
814 cd40dc53 Michael Hanselmann
815 cd40dc53 Michael Hanselmann
    # Resolver using configuration
816 d5ea30e8 Michael Hanselmann
    resolver = compat.partial(_NodeConfigResolver, cfg.GetNodeInfo,
817 d5ea30e8 Michael Hanselmann
                              cfg.GetAllNodesInfo)
818 cd40dc53 Michael Hanselmann
819 db04ce5d Michael Hanselmann
    # Pylint doesn't recognize multiple inheritance properly, see
820 db04ce5d Michael Hanselmann
    # <http://www.logilab.org/ticket/36586> and
821 db04ce5d Michael Hanselmann
    # <http://www.logilab.org/ticket/35642>
822 db04ce5d Michael Hanselmann
    # pylint: disable=W0233
823 cd40dc53 Michael Hanselmann
    _RpcClientBase.__init__(self, resolver, encoders.get,
824 d5ea30e8 Michael Hanselmann
                            lock_monitor_cb=lock_monitor_cb,
825 d5ea30e8 Michael Hanselmann
                            _req_process_fn=_req_process_fn)
826 415a7304 Michael Hanselmann
    _generated_rpc.RpcClientConfig.__init__(self)
827 db04ce5d Michael Hanselmann
    _generated_rpc.RpcClientBootstrap.__init__(self)
828 bd6d1202 René Nussbaumer
    _generated_rpc.RpcClientDnsOnly.__init__(self)
829 200de241 Michael Hanselmann
    _generated_rpc.RpcClientDefault.__init__(self)
830 200de241 Michael Hanselmann
831 0c3d9c7c Thomas Thrainer
  def _NicDict(self, _, nic):
832 cbe4a0a5 Dimitris Aragiorgis
    """Convert the given nic to a dict and encapsulate netinfo
833 cbe4a0a5 Dimitris Aragiorgis

834 cbe4a0a5 Dimitris Aragiorgis
    """
835 cbe4a0a5 Dimitris Aragiorgis
    n = copy.deepcopy(nic)
836 cbe4a0a5 Dimitris Aragiorgis
    if n.network:
837 cbe4a0a5 Dimitris Aragiorgis
      net_uuid = self._cfg.LookupNetwork(n.network)
838 cbe4a0a5 Dimitris Aragiorgis
      if net_uuid:
839 cbe4a0a5 Dimitris Aragiorgis
        nobj = self._cfg.GetNetwork(net_uuid)
840 cbe4a0a5 Dimitris Aragiorgis
        n.netinfo = objects.Network.ToDict(nobj)
841 cbe4a0a5 Dimitris Aragiorgis
    return n.ToDict()
842 cbe4a0a5 Dimitris Aragiorgis
843 51951d38 Dimitris Aragiorgis
  def _DeviceDict(self, _, (device, instance)):
844 c5708931 Dimitris Aragiorgis
    if isinstance(device, objects.NIC):
845 c5708931 Dimitris Aragiorgis
      return self._NicDict(None, device)
846 c5708931 Dimitris Aragiorgis
    elif isinstance(device, objects.Disk):
847 51951d38 Dimitris Aragiorgis
      return self._SingleDiskDictDP(None, (device, instance))
848 c5708931 Dimitris Aragiorgis
849 0c3d9c7c Thomas Thrainer
  def _InstDict(self, node, instance, hvp=None, bep=None, osp=None):
850 26ba2bd8 Iustin Pop
    """Convert the given instance to a dict.
851 26ba2bd8 Iustin Pop

852 26ba2bd8 Iustin Pop
    This is done via the instance's ToDict() method and additionally
853 26ba2bd8 Iustin Pop
    we fill the hvparams with the cluster defaults.
854 26ba2bd8 Iustin Pop

855 26ba2bd8 Iustin Pop
    @type instance: L{objects.Instance}
856 26ba2bd8 Iustin Pop
    @param instance: an Instance object
857 0eca8e0c Iustin Pop
    @type hvp: dict or None
858 5bbd3f7f Michael Hanselmann
    @param hvp: a dictionary with overridden hypervisor parameters
859 0eca8e0c Iustin Pop
    @type bep: dict or None
860 5bbd3f7f Michael Hanselmann
    @param bep: a dictionary with overridden backend parameters
861 1bdcbbab Iustin Pop
    @type osp: dict or None
862 8d8c4eff Michael Hanselmann
    @param osp: a dictionary with overridden os parameters
863 26ba2bd8 Iustin Pop
    @rtype: dict
864 26ba2bd8 Iustin Pop
    @return: the instance dict, with the hvparams filled with the
865 26ba2bd8 Iustin Pop
        cluster defaults
866 26ba2bd8 Iustin Pop

867 26ba2bd8 Iustin Pop
    """
868 26ba2bd8 Iustin Pop
    idict = instance.ToDict()
869 5b442704 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
870 5b442704 Iustin Pop
    idict["hvparams"] = cluster.FillHV(instance)
871 0eca8e0c Iustin Pop
    if hvp is not None:
872 0eca8e0c Iustin Pop
      idict["hvparams"].update(hvp)
873 5b442704 Iustin Pop
    idict["beparams"] = cluster.FillBE(instance)
874 0eca8e0c Iustin Pop
    if bep is not None:
875 0eca8e0c Iustin Pop
      idict["beparams"].update(bep)
876 1bdcbbab Iustin Pop
    idict["osparams"] = cluster.SimpleFillOS(instance.os, instance.osparams)
877 1bdcbbab Iustin Pop
    if osp is not None:
878 1bdcbbab Iustin Pop
      idict["osparams"].update(osp)
879 0c3d9c7c Thomas Thrainer
    idict["disks"] = self._DisksDictDP(node, (instance.disks, instance))
880 b848ce79 Guido Trotter
    for nic in idict["nics"]:
881 3ccb3a64 Michael Hanselmann
      nic["nicparams"] = objects.FillDict(
882 b848ce79 Guido Trotter
        cluster.nicparams[constants.PP_DEFAULT],
883 3ccb3a64 Michael Hanselmann
        nic["nicparams"])
884 cbe4a0a5 Dimitris Aragiorgis
      network = nic.get("network", None)
885 cbe4a0a5 Dimitris Aragiorgis
      if network:
886 cbe4a0a5 Dimitris Aragiorgis
        net_uuid = self._cfg.LookupNetwork(network)
887 cbe4a0a5 Dimitris Aragiorgis
        if net_uuid:
888 cbe4a0a5 Dimitris Aragiorgis
          nobj = self._cfg.GetNetwork(net_uuid)
889 cbe4a0a5 Dimitris Aragiorgis
          nic["netinfo"] = objects.Network.ToDict(nobj)
890 26ba2bd8 Iustin Pop
    return idict
891 26ba2bd8 Iustin Pop
892 0c3d9c7c Thomas Thrainer
  def _InstDictHvpBepDp(self, node, (instance, hvp, bep)):
893 c4de9b7a Michael Hanselmann
    """Wrapper for L{_InstDict}.
894 c4de9b7a Michael Hanselmann

895 c4de9b7a Michael Hanselmann
    """
896 0c3d9c7c Thomas Thrainer
    return self._InstDict(node, instance, hvp=hvp, bep=bep)
897 c4de9b7a Michael Hanselmann
898 0c3d9c7c Thomas Thrainer
  def _InstDictOspDp(self, node, (instance, osparams)):
899 c4de9b7a Michael Hanselmann
    """Wrapper for L{_InstDict}.
900 c4de9b7a Michael Hanselmann

901 c4de9b7a Michael Hanselmann
    """
902 0c3d9c7c Thomas Thrainer
    return self._InstDict(node, instance, osp=osparams)
903 c4de9b7a Michael Hanselmann
904 0c3d9c7c Thomas Thrainer
  def _DisksDictDP(self, node, (disks, instance)):
905 aedf5fd7 René Nussbaumer
    """Wrapper for L{AnnotateDiskParams}.
906 aedf5fd7 René Nussbaumer

907 aedf5fd7 René Nussbaumer
    """
908 aedf5fd7 René Nussbaumer
    diskparams = self._cfg.GetInstanceDiskParams(instance)
909 0c3d9c7c Thomas Thrainer
    ret = []
910 0c3d9c7c Thomas Thrainer
    for disk in AnnotateDiskParams(disks, diskparams):
911 0c3d9c7c Thomas Thrainer
      disk_node_uuids = disk.GetNodes(instance.primary_node)
912 0c3d9c7c Thomas Thrainer
      node_ips = dict((uuid, node.secondary_ip) for (uuid, node)
913 0c3d9c7c Thomas Thrainer
                      in self._cfg.GetMultiNodeInfo(disk_node_uuids))
914 0c3d9c7c Thomas Thrainer
915 0c3d9c7c Thomas Thrainer
      disk.UpdateDynamicDiskParams(node, node_ips)
916 0c3d9c7c Thomas Thrainer
917 a0d2a91e Thomas Thrainer
      ret.append(disk.ToDict(include_dynamic_params=True))
918 aedf5fd7 René Nussbaumer
919 0c3d9c7c Thomas Thrainer
    return ret
920 0c3d9c7c Thomas Thrainer
921 0c3d9c7c Thomas Thrainer
  def _MultiDiskDictDP(self, node, disks_insts):
922 235a6b29 Thomas Thrainer
    """Wrapper for L{AnnotateDiskParams}.
923 235a6b29 Thomas Thrainer

924 235a6b29 Thomas Thrainer
    Supports a list of (disk, instance) tuples.
925 235a6b29 Thomas Thrainer
    """
926 235a6b29 Thomas Thrainer
    return [disk for disk_inst in disks_insts
927 0c3d9c7c Thomas Thrainer
            for disk in self._DisksDictDP(node, disk_inst)]
928 235a6b29 Thomas Thrainer
929 0c3d9c7c Thomas Thrainer
  def _SingleDiskDictDP(self, node, (disk, instance)):
930 aedf5fd7 René Nussbaumer
    """Wrapper for L{AnnotateDiskParams}.
931 aedf5fd7 René Nussbaumer

932 aedf5fd7 René Nussbaumer
    """
933 0c3d9c7c Thomas Thrainer
    (anno_disk,) = self._DisksDictDP(node, ([disk], instance))
934 aedf5fd7 René Nussbaumer
    return anno_disk
935 aedf5fd7 René Nussbaumer
936 0c3d9c7c Thomas Thrainer
  def _EncodeNodeToDiskDictDP(self, node, value):
937 0c3d9c7c Thomas Thrainer
    """Encode dict of node name -> list of (disk, instance) tuples as values.
938 0c3d9c7c Thomas Thrainer

939 0c3d9c7c Thomas Thrainer
    """
940 0c3d9c7c Thomas Thrainer
    return dict((name, [self._SingleDiskDictDP(node, disk) for disk in disks])
941 0c3d9c7c Thomas Thrainer
                for name, disks in value.items())
942 0c3d9c7c Thomas Thrainer
943 0c3d9c7c Thomas Thrainer
  def _EncodeImportExportIO(self, node, (ieio, ieioargs)):
944 0c3d9c7c Thomas Thrainer
    """Encodes import/export I/O information.
945 0c3d9c7c Thomas Thrainer

946 0c3d9c7c Thomas Thrainer
    """
947 0c3d9c7c Thomas Thrainer
    if ieio == constants.IEIO_RAW_DISK:
948 063613aa Thomas Thrainer
      assert len(ieioargs) == 2
949 063613aa Thomas Thrainer
      return (ieio, (self._SingleDiskDictDP(node, ieioargs), ))
950 0c3d9c7c Thomas Thrainer
951 0c3d9c7c Thomas Thrainer
    if ieio == constants.IEIO_SCRIPT:
952 0c3d9c7c Thomas Thrainer
      assert len(ieioargs) == 2
953 0c3d9c7c Thomas Thrainer
      return (ieio, (self._SingleDiskDictDP(node, ieioargs[0]), ieioargs[1]))
954 0c3d9c7c Thomas Thrainer
955 0c3d9c7c Thomas Thrainer
    return (ieio, ieioargs)
956 0c3d9c7c Thomas Thrainer
957 fb1ffbca Michael Hanselmann
958 cd40dc53 Michael Hanselmann
class JobQueueRunner(_RpcClientBase, _generated_rpc.RpcClientJobQueue):
959 fb1ffbca Michael Hanselmann
  """RPC wrappers for job queue.
960 fb1ffbca Michael Hanselmann

961 fb1ffbca Michael Hanselmann
  """
962 fb1ffbca Michael Hanselmann
  def __init__(self, context, address_list):
963 fb1ffbca Michael Hanselmann
    """Initializes this class.
964 fb1ffbca Michael Hanselmann

965 fb1ffbca Michael Hanselmann
    """
966 fb1ffbca Michael Hanselmann
    if address_list is None:
967 bd6d1202 René Nussbaumer
      resolver = compat.partial(_SsconfResolver, True)
968 fb1ffbca Michael Hanselmann
    else:
969 fb1ffbca Michael Hanselmann
      # Caller provided an address list
970 fb1ffbca Michael Hanselmann
      resolver = _StaticResolver(address_list)
971 fb1ffbca Michael Hanselmann
972 cd40dc53 Michael Hanselmann
    _RpcClientBase.__init__(self, resolver, _ENCODERS.get,
973 cd40dc53 Michael Hanselmann
                            lock_monitor_cb=context.glm.AddToLockMonitor)
974 cd40dc53 Michael Hanselmann
    _generated_rpc.RpcClientJobQueue.__init__(self)
975 db04ce5d Michael Hanselmann
976 db04ce5d Michael Hanselmann
977 bd6d1202 René Nussbaumer
class BootstrapRunner(_RpcClientBase,
978 bd6d1202 René Nussbaumer
                      _generated_rpc.RpcClientBootstrap,
979 bd6d1202 René Nussbaumer
                      _generated_rpc.RpcClientDnsOnly):
980 db04ce5d Michael Hanselmann
  """RPC wrappers for bootstrapping.
981 db04ce5d Michael Hanselmann

982 db04ce5d Michael Hanselmann
  """
983 db04ce5d Michael Hanselmann
  def __init__(self):
984 db04ce5d Michael Hanselmann
    """Initializes this class.
985 db04ce5d Michael Hanselmann

986 db04ce5d Michael Hanselmann
    """
987 bd6d1202 René Nussbaumer
    # Pylint doesn't recognize multiple inheritance properly, see
988 bd6d1202 René Nussbaumer
    # <http://www.logilab.org/ticket/36586> and
989 bd6d1202 René Nussbaumer
    # <http://www.logilab.org/ticket/35642>
990 bd6d1202 René Nussbaumer
    # pylint: disable=W0233
991 bd6d1202 René Nussbaumer
    _RpcClientBase.__init__(self, compat.partial(_SsconfResolver, True),
992 bd6d1202 René Nussbaumer
                            _ENCODERS.get)
993 db04ce5d Michael Hanselmann
    _generated_rpc.RpcClientBootstrap.__init__(self)
994 bd6d1202 René Nussbaumer
    _generated_rpc.RpcClientDnsOnly.__init__(self)
995 bd6d1202 René Nussbaumer
996 bd6d1202 René Nussbaumer
997 bd6d1202 René Nussbaumer
class DnsOnlyRunner(_RpcClientBase, _generated_rpc.RpcClientDnsOnly):
998 bd6d1202 René Nussbaumer
  """RPC wrappers for calls using only DNS.
999 bd6d1202 René Nussbaumer

1000 bd6d1202 René Nussbaumer
  """
1001 bd6d1202 René Nussbaumer
  def __init__(self):
1002 bd6d1202 René Nussbaumer
    """Initialize this class.
1003 bd6d1202 René Nussbaumer

1004 bd6d1202 René Nussbaumer
    """
1005 bd6d1202 René Nussbaumer
    _RpcClientBase.__init__(self, compat.partial(_SsconfResolver, False),
1006 bd6d1202 René Nussbaumer
                            _ENCODERS.get)
1007 bd6d1202 René Nussbaumer
    _generated_rpc.RpcClientDnsOnly.__init__(self)
1008 db04ce5d Michael Hanselmann
1009 415a7304 Michael Hanselmann
1010 cd40dc53 Michael Hanselmann
class ConfigRunner(_RpcClientBase, _generated_rpc.RpcClientConfig):
1011 415a7304 Michael Hanselmann
  """RPC wrappers for L{config}.
1012 415a7304 Michael Hanselmann

1013 415a7304 Michael Hanselmann
  """
1014 c2dc025a Michael Hanselmann
  def __init__(self, context, address_list, _req_process_fn=None,
1015 c2dc025a Michael Hanselmann
               _getents=None):
1016 415a7304 Michael Hanselmann
    """Initializes this class.
1017 415a7304 Michael Hanselmann

1018 415a7304 Michael Hanselmann
    """
1019 b2acdbdc Michael Hanselmann
    if context:
1020 b2acdbdc Michael Hanselmann
      lock_monitor_cb = context.glm.AddToLockMonitor
1021 b2acdbdc Michael Hanselmann
    else:
1022 b2acdbdc Michael Hanselmann
      lock_monitor_cb = None
1023 b2acdbdc Michael Hanselmann
1024 415a7304 Michael Hanselmann
    if address_list is None:
1025 bd6d1202 René Nussbaumer
      resolver = compat.partial(_SsconfResolver, True)
1026 415a7304 Michael Hanselmann
    else:
1027 415a7304 Michael Hanselmann
      # Caller provided an address list
1028 415a7304 Michael Hanselmann
      resolver = _StaticResolver(address_list)
1029 415a7304 Michael Hanselmann
1030 c2dc025a Michael Hanselmann
    encoders = _ENCODERS.copy()
1031 c2dc025a Michael Hanselmann
1032 c2dc025a Michael Hanselmann
    encoders.update({
1033 c2dc025a Michael Hanselmann
      rpc_defs.ED_FILE_DETAILS: compat.partial(_PrepareFileUpload, _getents),
1034 c2dc025a Michael Hanselmann
      })
1035 c2dc025a Michael Hanselmann
1036 c2dc025a Michael Hanselmann
    _RpcClientBase.__init__(self, resolver, encoders.get,
1037 c2dc025a Michael Hanselmann
                            lock_monitor_cb=lock_monitor_cb,
1038 c2dc025a Michael Hanselmann
                            _req_process_fn=_req_process_fn)
1039 cd40dc53 Michael Hanselmann
    _generated_rpc.RpcClientConfig.__init__(self)