Statistics
| Branch: | Tag: | Revision:

root / lib / luxi.py @ 1094acda

History | View | Annotate | Download (10.6 kB)

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

24 8d5b316c Iustin Pop
This module implements the local unix socket protocol. You only need
25 c2a03789 Iustin Pop
this module and the opcodes module in the client program in order to
26 c2a03789 Iustin Pop
communicate with the master.
27 c2a03789 Iustin Pop

28 7577196d Guido Trotter
The module is also used by the master daemon.
29 c2a03789 Iustin Pop

30 c2a03789 Iustin Pop
"""
31 c2a03789 Iustin Pop
32 c2a03789 Iustin Pop
import socket
33 c2a03789 Iustin Pop
import collections
34 c2a03789 Iustin Pop
import time
35 03a8dbdc Iustin Pop
import errno
36 c2a03789 Iustin Pop
37 fad50141 Michael Hanselmann
from ganeti import serializer
38 ceab32dd Iustin Pop
from ganeti import constants
39 6797ec29 Iustin Pop
from ganeti import errors
40 c2a03789 Iustin Pop
41 c2a03789 Iustin Pop
42 3d8548c4 Michael Hanselmann
KEY_METHOD = 'method'
43 3d8548c4 Michael Hanselmann
KEY_ARGS = 'args'
44 3d8548c4 Michael Hanselmann
KEY_SUCCESS = "success"
45 3d8548c4 Michael Hanselmann
KEY_RESULT = "result"
46 3d8548c4 Michael Hanselmann
47 0bbe448c Michael Hanselmann
REQ_SUBMIT_JOB = "SubmitJob"
48 2971c913 Iustin Pop
REQ_SUBMIT_MANY_JOBS = "SubmitManyJobs"
49 dfe57c22 Michael Hanselmann
REQ_WAIT_FOR_JOB_CHANGE = "WaitForJobChange"
50 0bbe448c Michael Hanselmann
REQ_CANCEL_JOB = "CancelJob"
51 0bbe448c Michael Hanselmann
REQ_ARCHIVE_JOB = "ArchiveJob"
52 07cd723a Iustin Pop
REQ_AUTOARCHIVE_JOBS = "AutoArchiveJobs"
53 0bbe448c Michael Hanselmann
REQ_QUERY_JOBS = "QueryJobs"
54 ee6c7b94 Michael Hanselmann
REQ_QUERY_INSTANCES = "QueryInstances"
55 02f7fe54 Michael Hanselmann
REQ_QUERY_NODES = "QueryNodes"
56 32f93223 Michael Hanselmann
REQ_QUERY_EXPORTS = "QueryExports"
57 ae5849b5 Michael Hanselmann
REQ_QUERY_CONFIG_VALUES = "QueryConfigValues"
58 66baeccc Iustin Pop
REQ_QUERY_CLUSTER_INFO = "QueryClusterInfo"
59 3ccafd0e Iustin Pop
REQ_QUEUE_SET_DRAIN_FLAG = "SetDrainFlag"
60 c2a03789 Iustin Pop
61 c2a03789 Iustin Pop
DEF_CTMO = 10
62 c2a03789 Iustin Pop
DEF_RWTO = 60
63 c2a03789 Iustin Pop
64 c2a03789 Iustin Pop
65 c2a03789 Iustin Pop
class ProtocolError(Exception):
66 c2a03789 Iustin Pop
  """Denotes an error in the server communication"""
67 c2a03789 Iustin Pop
68 c2a03789 Iustin Pop
69 c2a03789 Iustin Pop
class ConnectionClosedError(ProtocolError):
70 c2a03789 Iustin Pop
  """Connection closed error"""
71 c2a03789 Iustin Pop
72 c2a03789 Iustin Pop
73 c2a03789 Iustin Pop
class TimeoutError(ProtocolError):
74 c2a03789 Iustin Pop
  """Operation timeout error"""
75 c2a03789 Iustin Pop
76 c2a03789 Iustin Pop
77 c2a03789 Iustin Pop
class EncodingError(ProtocolError):
78 c2a03789 Iustin Pop
  """Encoding failure on the sending side"""
79 c2a03789 Iustin Pop
80 c2a03789 Iustin Pop
81 c2a03789 Iustin Pop
class DecodingError(ProtocolError):
82 c2a03789 Iustin Pop
  """Decoding failure on the receiving side"""
83 c2a03789 Iustin Pop
84 c2a03789 Iustin Pop
85 b77acb3e Iustin Pop
class RequestError(ProtocolError):
86 b77acb3e Iustin Pop
  """Error on request
87 b77acb3e Iustin Pop

88 b77acb3e Iustin Pop
  This signifies an error in the request format or request handling,
89 b77acb3e Iustin Pop
  but not (e.g.) an error in starting up an instance.
90 b77acb3e Iustin Pop

91 b77acb3e Iustin Pop
  Some common conditions that can trigger this exception:
92 b77acb3e Iustin Pop
    - job submission failed because the job data was wrong
93 b77acb3e Iustin Pop
    - query failed because required fields were missing
94 b77acb3e Iustin Pop

95 b77acb3e Iustin Pop
  """
96 b77acb3e Iustin Pop
97 3d8548c4 Michael Hanselmann
98 03a8dbdc Iustin Pop
class NoMasterError(ProtocolError):
99 03a8dbdc Iustin Pop
  """The master cannot be reached
100 03a8dbdc Iustin Pop

101 03a8dbdc Iustin Pop
  This means that the master daemon is not running or the socket has
102 03a8dbdc Iustin Pop
  been removed.
103 03a8dbdc Iustin Pop

104 03a8dbdc Iustin Pop
  """
105 03a8dbdc Iustin Pop
106 b77acb3e Iustin Pop
107 c2a03789 Iustin Pop
class Transport:
108 c2a03789 Iustin Pop
  """Low-level transport class.
109 c2a03789 Iustin Pop

110 c2a03789 Iustin Pop
  This is used on the client side.
111 c2a03789 Iustin Pop

112 c2a03789 Iustin Pop
  This could be replace by any other class that provides the same
113 c2a03789 Iustin Pop
  semantics to the Client. This means:
114 c2a03789 Iustin Pop
    - can send messages and receive messages
115 c2a03789 Iustin Pop
    - safe for multithreading
116 c2a03789 Iustin Pop

117 c2a03789 Iustin Pop
  """
118 c2a03789 Iustin Pop
119 c2a03789 Iustin Pop
  def __init__(self, address, timeouts=None, eom=None):
120 c2a03789 Iustin Pop
    """Constructor for the Client class.
121 c2a03789 Iustin Pop

122 c2a03789 Iustin Pop
    Arguments:
123 c2a03789 Iustin Pop
      - address: a valid address the the used transport class
124 c2a03789 Iustin Pop
      - timeout: a list of timeouts, to be used on connect and read/write
125 c2a03789 Iustin Pop
      - eom: an identifier to be used as end-of-message which the
126 c2a03789 Iustin Pop
        upper-layer will guarantee that this identifier will not appear
127 c2a03789 Iustin Pop
        in any message
128 c2a03789 Iustin Pop

129 c2a03789 Iustin Pop
    There are two timeouts used since we might want to wait for a long
130 c2a03789 Iustin Pop
    time for a response, but the connect timeout should be lower.
131 c2a03789 Iustin Pop

132 c2a03789 Iustin Pop
    If not passed, we use a default of 10 and respectively 60 seconds.
133 c2a03789 Iustin Pop

134 c2a03789 Iustin Pop
    Note that on reading data, since the timeout applies to an
135 c2a03789 Iustin Pop
    invidual receive, it might be that the total duration is longer
136 c2a03789 Iustin Pop
    than timeout value passed (we make a hard limit at twice the read
137 c2a03789 Iustin Pop
    timeout).
138 c2a03789 Iustin Pop

139 c2a03789 Iustin Pop
    """
140 c2a03789 Iustin Pop
    self.address = address
141 c2a03789 Iustin Pop
    if timeouts is None:
142 c2a03789 Iustin Pop
      self._ctimeout, self._rwtimeout = DEF_CTMO, DEF_RWTO
143 c2a03789 Iustin Pop
    else:
144 c2a03789 Iustin Pop
      self._ctimeout, self._rwtimeout = timeouts
145 c2a03789 Iustin Pop
146 c2a03789 Iustin Pop
    self.socket = None
147 c2a03789 Iustin Pop
    self._buffer = ""
148 c2a03789 Iustin Pop
    self._msgs = collections.deque()
149 c2a03789 Iustin Pop
150 c2a03789 Iustin Pop
    if eom is None:
151 c2a03789 Iustin Pop
      self.eom = '\3'
152 c2a03789 Iustin Pop
    else:
153 c2a03789 Iustin Pop
      self.eom = eom
154 c2a03789 Iustin Pop
155 c2a03789 Iustin Pop
    try:
156 c2a03789 Iustin Pop
      self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
157 c2a03789 Iustin Pop
      self.socket.settimeout(self._ctimeout)
158 c2a03789 Iustin Pop
      try:
159 c2a03789 Iustin Pop
        self.socket.connect(address)
160 c2a03789 Iustin Pop
      except socket.timeout, err:
161 03a8dbdc Iustin Pop
        raise TimeoutError("Connect timed out: %s" % str(err))
162 03a8dbdc Iustin Pop
      except socket.error, err:
163 082c5adb Michael Hanselmann
        if err.args[0] in (errno.ENOENT, errno.ECONNREFUSED):
164 03a8dbdc Iustin Pop
          raise NoMasterError((address,))
165 03a8dbdc Iustin Pop
        raise
166 c2a03789 Iustin Pop
      self.socket.settimeout(self._rwtimeout)
167 03a8dbdc Iustin Pop
    except (socket.error, NoMasterError):
168 c2a03789 Iustin Pop
      if self.socket is not None:
169 c2a03789 Iustin Pop
        self.socket.close()
170 c2a03789 Iustin Pop
      self.socket = None
171 c2a03789 Iustin Pop
      raise
172 c2a03789 Iustin Pop
173 c2a03789 Iustin Pop
  def _CheckSocket(self):
174 c2a03789 Iustin Pop
    """Make sure we are connected.
175 c2a03789 Iustin Pop

176 c2a03789 Iustin Pop
    """
177 c2a03789 Iustin Pop
    if self.socket is None:
178 c2a03789 Iustin Pop
      raise ProtocolError("Connection is closed")
179 c2a03789 Iustin Pop
180 c2a03789 Iustin Pop
  def Send(self, msg):
181 c2a03789 Iustin Pop
    """Send a message.
182 c2a03789 Iustin Pop

183 c2a03789 Iustin Pop
    This just sends a message and doesn't wait for the response.
184 c2a03789 Iustin Pop

185 c2a03789 Iustin Pop
    """
186 c2a03789 Iustin Pop
    if self.eom in msg:
187 c2a03789 Iustin Pop
      raise EncodingError("Message terminator found in payload")
188 c2a03789 Iustin Pop
    self._CheckSocket()
189 c2a03789 Iustin Pop
    try:
190 c2a03789 Iustin Pop
      self.socket.sendall(msg + self.eom)
191 c2a03789 Iustin Pop
    except socket.timeout, err:
192 c2a03789 Iustin Pop
      raise TimeoutError("Sending timeout: %s" % str(err))
193 c2a03789 Iustin Pop
194 c2a03789 Iustin Pop
  def Recv(self):
195 c2a03789 Iustin Pop
    """Try to receive a messae from the socket.
196 c2a03789 Iustin Pop

197 c2a03789 Iustin Pop
    In case we already have messages queued, we just return from the
198 c2a03789 Iustin Pop
    queue. Otherwise, we try to read data with a _rwtimeout network
199 c2a03789 Iustin Pop
    timeout, and making sure we don't go over 2x_rwtimeout as a global
200 c2a03789 Iustin Pop
    limit.
201 c2a03789 Iustin Pop

202 c2a03789 Iustin Pop
    """
203 c2a03789 Iustin Pop
    self._CheckSocket()
204 c2a03789 Iustin Pop
    etime = time.time() + self._rwtimeout
205 c2a03789 Iustin Pop
    while not self._msgs:
206 c2a03789 Iustin Pop
      if time.time() > etime:
207 c2a03789 Iustin Pop
        raise TimeoutError("Extended receive timeout")
208 c2a03789 Iustin Pop
      try:
209 c2a03789 Iustin Pop
        data = self.socket.recv(4096)
210 c2a03789 Iustin Pop
      except socket.timeout, err:
211 c2a03789 Iustin Pop
        raise TimeoutError("Receive timeout: %s" % str(err))
212 c2a03789 Iustin Pop
      if not data:
213 c2a03789 Iustin Pop
        raise ConnectionClosedError("Connection closed while reading")
214 c2a03789 Iustin Pop
      new_msgs = (self._buffer + data).split(self.eom)
215 c2a03789 Iustin Pop
      self._buffer = new_msgs.pop()
216 c2a03789 Iustin Pop
      self._msgs.extend(new_msgs)
217 c2a03789 Iustin Pop
    return self._msgs.popleft()
218 c2a03789 Iustin Pop
219 c2a03789 Iustin Pop
  def Call(self, msg):
220 c2a03789 Iustin Pop
    """Send a message and wait for the response.
221 c2a03789 Iustin Pop

222 c2a03789 Iustin Pop
    This is just a wrapper over Send and Recv.
223 c2a03789 Iustin Pop

224 c2a03789 Iustin Pop
    """
225 c2a03789 Iustin Pop
    self.Send(msg)
226 c2a03789 Iustin Pop
    return self.Recv()
227 c2a03789 Iustin Pop
228 c2a03789 Iustin Pop
  def Close(self):
229 c2a03789 Iustin Pop
    """Close the socket"""
230 c2a03789 Iustin Pop
    if self.socket is not None:
231 c2a03789 Iustin Pop
      self.socket.close()
232 c2a03789 Iustin Pop
      self.socket = None
233 c2a03789 Iustin Pop
234 c2a03789 Iustin Pop
235 c2a03789 Iustin Pop
class Client(object):
236 c2a03789 Iustin Pop
  """High-level client implementation.
237 c2a03789 Iustin Pop

238 c2a03789 Iustin Pop
  This uses a backing Transport-like class on top of which it
239 c2a03789 Iustin Pop
  implements data serialization/deserialization.
240 c2a03789 Iustin Pop

241 c2a03789 Iustin Pop
  """
242 ceab32dd Iustin Pop
  def __init__(self, address=None, timeouts=None, transport=Transport):
243 c2a03789 Iustin Pop
    """Constructor for the Client class.
244 c2a03789 Iustin Pop

245 c2a03789 Iustin Pop
    Arguments:
246 c2a03789 Iustin Pop
      - address: a valid address the the used transport class
247 c2a03789 Iustin Pop
      - timeout: a list of timeouts, to be used on connect and read/write
248 c2a03789 Iustin Pop
      - transport: a Transport-like class
249 c2a03789 Iustin Pop

250 c2a03789 Iustin Pop

251 c2a03789 Iustin Pop
    If timeout is not passed, the default timeouts of the transport
252 c2a03789 Iustin Pop
    class are used.
253 c2a03789 Iustin Pop

254 c2a03789 Iustin Pop
    """
255 ceab32dd Iustin Pop
    if address is None:
256 ceab32dd Iustin Pop
      address = constants.MASTER_SOCKET
257 8d5b316c Iustin Pop
    self.address = address
258 8d5b316c Iustin Pop
    self.timeouts = timeouts
259 8d5b316c Iustin Pop
    self.transport_class = transport
260 8d5b316c Iustin Pop
    self.transport = None
261 8d5b316c Iustin Pop
    self._InitTransport()
262 8d5b316c Iustin Pop
263 8d5b316c Iustin Pop
  def _InitTransport(self):
264 8d5b316c Iustin Pop
    """(Re)initialize the transport if needed.
265 8d5b316c Iustin Pop

266 8d5b316c Iustin Pop
    """
267 8d5b316c Iustin Pop
    if self.transport is None:
268 8d5b316c Iustin Pop
      self.transport = self.transport_class(self.address,
269 8d5b316c Iustin Pop
                                            timeouts=self.timeouts)
270 8d5b316c Iustin Pop
271 8d5b316c Iustin Pop
  def _CloseTransport(self):
272 8d5b316c Iustin Pop
    """Close the transport, ignoring errors.
273 8d5b316c Iustin Pop

274 8d5b316c Iustin Pop
    """
275 8d5b316c Iustin Pop
    if self.transport is None:
276 8d5b316c Iustin Pop
      return
277 8d5b316c Iustin Pop
    try:
278 8d5b316c Iustin Pop
      old_transp = self.transport
279 8d5b316c Iustin Pop
      self.transport = None
280 8d5b316c Iustin Pop
      old_transp.Close()
281 8d5b316c Iustin Pop
    except Exception, err:
282 8d5b316c Iustin Pop
      pass
283 c2a03789 Iustin Pop
284 3d8548c4 Michael Hanselmann
  def CallMethod(self, method, args):
285 c2a03789 Iustin Pop
    """Send a generic request and return the response.
286 c2a03789 Iustin Pop

287 c2a03789 Iustin Pop
    """
288 3d8548c4 Michael Hanselmann
    # Build request
289 3d8548c4 Michael Hanselmann
    request = {
290 3d8548c4 Michael Hanselmann
      KEY_METHOD: method,
291 3d8548c4 Michael Hanselmann
      KEY_ARGS: args,
292 3d8548c4 Michael Hanselmann
      }
293 3d8548c4 Michael Hanselmann
294 8d5b316c Iustin Pop
    # Serialize the request
295 8d5b316c Iustin Pop
    send_data = serializer.DumpJson(request, indent=False)
296 8d5b316c Iustin Pop
297 3d8548c4 Michael Hanselmann
    # Send request and wait for response
298 8d5b316c Iustin Pop
    try:
299 8d5b316c Iustin Pop
      self._InitTransport()
300 8d5b316c Iustin Pop
      result = self.transport.Call(send_data)
301 8d5b316c Iustin Pop
    except Exception:
302 8d5b316c Iustin Pop
      self._CloseTransport()
303 8d5b316c Iustin Pop
      raise
304 8d5b316c Iustin Pop
305 8d5b316c Iustin Pop
    # Parse the result
306 c2a03789 Iustin Pop
    try:
307 fad50141 Michael Hanselmann
      data = serializer.LoadJson(result)
308 c2a03789 Iustin Pop
    except Exception, err:
309 c2a03789 Iustin Pop
      raise ProtocolError("Error while deserializing response: %s" % str(err))
310 3d8548c4 Michael Hanselmann
311 3d8548c4 Michael Hanselmann
    # Validate response
312 a14a17fc Iustin Pop
    if (not isinstance(data, dict) or
313 3d8548c4 Michael Hanselmann
        KEY_SUCCESS not in data or
314 3d8548c4 Michael Hanselmann
        KEY_RESULT not in data):
315 a14a17fc Iustin Pop
      raise DecodingError("Invalid response from server: %s" % str(data))
316 3d8548c4 Michael Hanselmann
317 6797ec29 Iustin Pop
    result = data[KEY_RESULT]
318 6797ec29 Iustin Pop
319 3d8548c4 Michael Hanselmann
    if not data[KEY_SUCCESS]:
320 3d8548c4 Michael Hanselmann
      # TODO: decide on a standard exception
321 6797ec29 Iustin Pop
      if (isinstance(result, (tuple, list)) and len(result) == 2 and
322 6797ec29 Iustin Pop
          isinstance(result[1], (tuple, list))):
323 6797ec29 Iustin Pop
        # custom ganeti errors
324 6797ec29 Iustin Pop
        err_class = errors.GetErrorClass(result[0])
325 6797ec29 Iustin Pop
        if err_class is not None:
326 6797ec29 Iustin Pop
          raise err_class, tuple(result[1])
327 6797ec29 Iustin Pop
328 6797ec29 Iustin Pop
      raise RequestError(result)
329 3d8548c4 Michael Hanselmann
330 6797ec29 Iustin Pop
    return result
331 c2a03789 Iustin Pop
332 3ccafd0e Iustin Pop
  def SetQueueDrainFlag(self, drain_flag):
333 3ccafd0e Iustin Pop
    return self.CallMethod(REQ_QUEUE_SET_DRAIN_FLAG, drain_flag)
334 3ccafd0e Iustin Pop
335 0bbe448c Michael Hanselmann
  def SubmitJob(self, ops):
336 0bbe448c Michael Hanselmann
    ops_state = map(lambda op: op.__getstate__(), ops)
337 0bbe448c Michael Hanselmann
    return self.CallMethod(REQ_SUBMIT_JOB, ops_state)
338 0bbe448c Michael Hanselmann
339 2971c913 Iustin Pop
  def SubmitManyJobs(self, jobs):
340 2971c913 Iustin Pop
    jobs_state = []
341 2971c913 Iustin Pop
    for ops in jobs:
342 2971c913 Iustin Pop
      jobs_state.append([op.__getstate__() for op in ops])
343 2971c913 Iustin Pop
    return self.CallMethod(REQ_SUBMIT_MANY_JOBS, jobs_state)
344 2971c913 Iustin Pop
345 0bbe448c Michael Hanselmann
  def CancelJob(self, job_id):
346 0bbe448c Michael Hanselmann
    return self.CallMethod(REQ_CANCEL_JOB, job_id)
347 0bbe448c Michael Hanselmann
348 0bbe448c Michael Hanselmann
  def ArchiveJob(self, job_id):
349 0bbe448c Michael Hanselmann
    return self.CallMethod(REQ_ARCHIVE_JOB, job_id)
350 0bbe448c Michael Hanselmann
351 07cd723a Iustin Pop
  def AutoArchiveJobs(self, age):
352 f8ad5591 Michael Hanselmann
    timeout = (DEF_RWTO - 1) / 2
353 f8ad5591 Michael Hanselmann
    return self.CallMethod(REQ_AUTOARCHIVE_JOBS, (age, timeout))
354 07cd723a Iustin Pop
355 6c5a7090 Michael Hanselmann
  def WaitForJobChange(self, job_id, fields, prev_job_info, prev_log_serial):
356 5c735209 Iustin Pop
    timeout = (DEF_RWTO - 1) / 2
357 5c735209 Iustin Pop
    while True:
358 5c735209 Iustin Pop
      result = self.CallMethod(REQ_WAIT_FOR_JOB_CHANGE,
359 5c735209 Iustin Pop
                               (job_id, fields, prev_job_info,
360 5c735209 Iustin Pop
                                prev_log_serial, timeout))
361 5c735209 Iustin Pop
      if result != constants.JOB_NOTCHANGED:
362 5c735209 Iustin Pop
        break
363 5c735209 Iustin Pop
    return result
364 dfe57c22 Michael Hanselmann
365 0bbe448c Michael Hanselmann
  def QueryJobs(self, job_ids, fields):
366 0bbe448c Michael Hanselmann
    return self.CallMethod(REQ_QUERY_JOBS, (job_ids, fields))
367 3d8548c4 Michael Hanselmann
368 ec79568d Iustin Pop
  def QueryInstances(self, names, fields, use_locking):
369 ec79568d Iustin Pop
    return self.CallMethod(REQ_QUERY_INSTANCES, (names, fields, use_locking))
370 ee6c7b94 Michael Hanselmann
371 ec79568d Iustin Pop
  def QueryNodes(self, names, fields, use_locking):
372 ec79568d Iustin Pop
    return self.CallMethod(REQ_QUERY_NODES, (names, fields, use_locking))
373 02f7fe54 Michael Hanselmann
374 ec79568d Iustin Pop
  def QueryExports(self, nodes, use_locking):
375 ec79568d Iustin Pop
    return self.CallMethod(REQ_QUERY_EXPORTS, (nodes, use_locking))
376 32f93223 Michael Hanselmann
377 66baeccc Iustin Pop
  def QueryClusterInfo(self):
378 66baeccc Iustin Pop
    return self.CallMethod(REQ_QUERY_CLUSTER_INFO, ())
379 66baeccc Iustin Pop
380 ae5849b5 Michael Hanselmann
  def QueryConfigValues(self, fields):
381 ae5849b5 Michael Hanselmann
    return self.CallMethod(REQ_QUERY_CONFIG_VALUES, fields)
382 ae5849b5 Michael Hanselmann
383 3ccafd0e Iustin Pop
384 3d8548c4 Michael Hanselmann
# TODO: class Server(object)