Statistics
| Branch: | Tag: | Revision:

root / lib / luxi.py @ 5ef5cfea

History | View | Annotate | Download (12.1 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 cb462b06 Michael Hanselmann
from ganeti import utils
41 c2a03789 Iustin Pop
42 c2a03789 Iustin Pop
43 3d8548c4 Michael Hanselmann
KEY_METHOD = 'method'
44 3d8548c4 Michael Hanselmann
KEY_ARGS = 'args'
45 3d8548c4 Michael Hanselmann
KEY_SUCCESS = "success"
46 3d8548c4 Michael Hanselmann
KEY_RESULT = "result"
47 3d8548c4 Michael Hanselmann
48 0bbe448c Michael Hanselmann
REQ_SUBMIT_JOB = "SubmitJob"
49 2971c913 Iustin Pop
REQ_SUBMIT_MANY_JOBS = "SubmitManyJobs"
50 dfe57c22 Michael Hanselmann
REQ_WAIT_FOR_JOB_CHANGE = "WaitForJobChange"
51 0bbe448c Michael Hanselmann
REQ_CANCEL_JOB = "CancelJob"
52 0bbe448c Michael Hanselmann
REQ_ARCHIVE_JOB = "ArchiveJob"
53 07cd723a Iustin Pop
REQ_AUTOARCHIVE_JOBS = "AutoArchiveJobs"
54 0bbe448c Michael Hanselmann
REQ_QUERY_JOBS = "QueryJobs"
55 ee6c7b94 Michael Hanselmann
REQ_QUERY_INSTANCES = "QueryInstances"
56 02f7fe54 Michael Hanselmann
REQ_QUERY_NODES = "QueryNodes"
57 32f93223 Michael Hanselmann
REQ_QUERY_EXPORTS = "QueryExports"
58 ae5849b5 Michael Hanselmann
REQ_QUERY_CONFIG_VALUES = "QueryConfigValues"
59 66baeccc Iustin Pop
REQ_QUERY_CLUSTER_INFO = "QueryClusterInfo"
60 7699c3af Iustin Pop
REQ_QUERY_TAGS = "QueryTags"
61 3ccafd0e Iustin Pop
REQ_QUEUE_SET_DRAIN_FLAG = "SetDrainFlag"
62 05e50653 Michael Hanselmann
REQ_SET_WATCHER_PAUSE = "SetWatcherPause"
63 c2a03789 Iustin Pop
64 c2a03789 Iustin Pop
DEF_CTMO = 10
65 c2a03789 Iustin Pop
DEF_RWTO = 60
66 c2a03789 Iustin Pop
67 793a8f7c Michael Hanselmann
# WaitForJobChange timeout
68 793a8f7c Michael Hanselmann
WFJC_TIMEOUT = (DEF_RWTO - 1) / 2
69 793a8f7c Michael Hanselmann
70 c2a03789 Iustin Pop
71 c2a03789 Iustin Pop
class ProtocolError(Exception):
72 c2a03789 Iustin Pop
  """Denotes an error in the server communication"""
73 c2a03789 Iustin Pop
74 c2a03789 Iustin Pop
75 c2a03789 Iustin Pop
class ConnectionClosedError(ProtocolError):
76 c2a03789 Iustin Pop
  """Connection closed error"""
77 c2a03789 Iustin Pop
78 c2a03789 Iustin Pop
79 c2a03789 Iustin Pop
class TimeoutError(ProtocolError):
80 c2a03789 Iustin Pop
  """Operation timeout error"""
81 c2a03789 Iustin Pop
82 c2a03789 Iustin Pop
83 c2a03789 Iustin Pop
class EncodingError(ProtocolError):
84 c2a03789 Iustin Pop
  """Encoding failure on the sending side"""
85 c2a03789 Iustin Pop
86 c2a03789 Iustin Pop
87 c2a03789 Iustin Pop
class DecodingError(ProtocolError):
88 c2a03789 Iustin Pop
  """Decoding failure on the receiving side"""
89 c2a03789 Iustin Pop
90 c2a03789 Iustin Pop
91 b77acb3e Iustin Pop
class RequestError(ProtocolError):
92 b77acb3e Iustin Pop
  """Error on request
93 b77acb3e Iustin Pop

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

97 b77acb3e Iustin Pop
  Some common conditions that can trigger this exception:
98 b77acb3e Iustin Pop
    - job submission failed because the job data was wrong
99 b77acb3e Iustin Pop
    - query failed because required fields were missing
100 b77acb3e Iustin Pop

101 b77acb3e Iustin Pop
  """
102 b77acb3e Iustin Pop
103 3d8548c4 Michael Hanselmann
104 03a8dbdc Iustin Pop
class NoMasterError(ProtocolError):
105 03a8dbdc Iustin Pop
  """The master cannot be reached
106 03a8dbdc Iustin Pop

107 03a8dbdc Iustin Pop
  This means that the master daemon is not running or the socket has
108 03a8dbdc Iustin Pop
  been removed.
109 03a8dbdc Iustin Pop

110 03a8dbdc Iustin Pop
  """
111 03a8dbdc Iustin Pop
112 b77acb3e Iustin Pop
113 c2a03789 Iustin Pop
class Transport:
114 c2a03789 Iustin Pop
  """Low-level transport class.
115 c2a03789 Iustin Pop

116 c2a03789 Iustin Pop
  This is used on the client side.
117 c2a03789 Iustin Pop

118 c2a03789 Iustin Pop
  This could be replace by any other class that provides the same
119 c2a03789 Iustin Pop
  semantics to the Client. This means:
120 c2a03789 Iustin Pop
    - can send messages and receive messages
121 c2a03789 Iustin Pop
    - safe for multithreading
122 c2a03789 Iustin Pop

123 c2a03789 Iustin Pop
  """
124 c2a03789 Iustin Pop
125 c2a03789 Iustin Pop
  def __init__(self, address, timeouts=None, eom=None):
126 c2a03789 Iustin Pop
    """Constructor for the Client class.
127 c2a03789 Iustin Pop

128 c2a03789 Iustin Pop
    Arguments:
129 c2a03789 Iustin Pop
      - address: a valid address the the used transport class
130 c2a03789 Iustin Pop
      - timeout: a list of timeouts, to be used on connect and read/write
131 c2a03789 Iustin Pop
      - eom: an identifier to be used as end-of-message which the
132 c2a03789 Iustin Pop
        upper-layer will guarantee that this identifier will not appear
133 c2a03789 Iustin Pop
        in any message
134 c2a03789 Iustin Pop

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

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

140 c2a03789 Iustin Pop
    Note that on reading data, since the timeout applies to an
141 c2a03789 Iustin Pop
    invidual receive, it might be that the total duration is longer
142 c2a03789 Iustin Pop
    than timeout value passed (we make a hard limit at twice the read
143 c2a03789 Iustin Pop
    timeout).
144 c2a03789 Iustin Pop

145 c2a03789 Iustin Pop
    """
146 c2a03789 Iustin Pop
    self.address = address
147 c2a03789 Iustin Pop
    if timeouts is None:
148 c2a03789 Iustin Pop
      self._ctimeout, self._rwtimeout = DEF_CTMO, DEF_RWTO
149 c2a03789 Iustin Pop
    else:
150 c2a03789 Iustin Pop
      self._ctimeout, self._rwtimeout = timeouts
151 c2a03789 Iustin Pop
152 c2a03789 Iustin Pop
    self.socket = None
153 c2a03789 Iustin Pop
    self._buffer = ""
154 c2a03789 Iustin Pop
    self._msgs = collections.deque()
155 c2a03789 Iustin Pop
156 c2a03789 Iustin Pop
    if eom is None:
157 c2a03789 Iustin Pop
      self.eom = '\3'
158 c2a03789 Iustin Pop
    else:
159 c2a03789 Iustin Pop
      self.eom = eom
160 c2a03789 Iustin Pop
161 c2a03789 Iustin Pop
    try:
162 c2a03789 Iustin Pop
      self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
163 cb462b06 Michael Hanselmann
164 cb462b06 Michael Hanselmann
      # Try to connect
165 c2a03789 Iustin Pop
      try:
166 cb462b06 Michael Hanselmann
        utils.Retry(self._Connect, 1.0, self._ctimeout,
167 cb462b06 Michael Hanselmann
                    args=(self.socket, address, self._ctimeout))
168 cb462b06 Michael Hanselmann
      except utils.RetryTimeout:
169 cb462b06 Michael Hanselmann
        raise TimeoutError("Connect timed out")
170 cb462b06 Michael Hanselmann
171 c2a03789 Iustin Pop
      self.socket.settimeout(self._rwtimeout)
172 03a8dbdc Iustin Pop
    except (socket.error, NoMasterError):
173 c2a03789 Iustin Pop
      if self.socket is not None:
174 c2a03789 Iustin Pop
        self.socket.close()
175 c2a03789 Iustin Pop
      self.socket = None
176 c2a03789 Iustin Pop
      raise
177 c2a03789 Iustin Pop
178 cb462b06 Michael Hanselmann
  @staticmethod
179 cb462b06 Michael Hanselmann
  def _Connect(sock, address, timeout):
180 cb462b06 Michael Hanselmann
    sock.settimeout(timeout)
181 cb462b06 Michael Hanselmann
    try:
182 cb462b06 Michael Hanselmann
      sock.connect(address)
183 cb462b06 Michael Hanselmann
    except socket.timeout, err:
184 cb462b06 Michael Hanselmann
      raise TimeoutError("Connect timed out: %s" % str(err))
185 cb462b06 Michael Hanselmann
    except socket.error, err:
186 cb462b06 Michael Hanselmann
      if err.args[0] in (errno.ENOENT, errno.ECONNREFUSED):
187 cb462b06 Michael Hanselmann
        raise NoMasterError(address)
188 cb462b06 Michael Hanselmann
      if err.args[0] == errno.EAGAIN:
189 cb462b06 Michael Hanselmann
        # Server's socket backlog is full at the moment
190 cb462b06 Michael Hanselmann
        raise utils.RetryAgain()
191 cb462b06 Michael Hanselmann
      raise
192 cb462b06 Michael Hanselmann
193 c2a03789 Iustin Pop
  def _CheckSocket(self):
194 c2a03789 Iustin Pop
    """Make sure we are connected.
195 c2a03789 Iustin Pop

196 c2a03789 Iustin Pop
    """
197 c2a03789 Iustin Pop
    if self.socket is None:
198 c2a03789 Iustin Pop
      raise ProtocolError("Connection is closed")
199 c2a03789 Iustin Pop
200 c2a03789 Iustin Pop
  def Send(self, msg):
201 c2a03789 Iustin Pop
    """Send a message.
202 c2a03789 Iustin Pop

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

205 c2a03789 Iustin Pop
    """
206 c2a03789 Iustin Pop
    if self.eom in msg:
207 c2a03789 Iustin Pop
      raise EncodingError("Message terminator found in payload")
208 c2a03789 Iustin Pop
    self._CheckSocket()
209 c2a03789 Iustin Pop
    try:
210 6096ee13 Michael Hanselmann
      # TODO: sendall is not guaranteed to send everything
211 c2a03789 Iustin Pop
      self.socket.sendall(msg + self.eom)
212 c2a03789 Iustin Pop
    except socket.timeout, err:
213 c2a03789 Iustin Pop
      raise TimeoutError("Sending timeout: %s" % str(err))
214 c2a03789 Iustin Pop
215 c2a03789 Iustin Pop
  def Recv(self):
216 5bbd3f7f Michael Hanselmann
    """Try to receive a message from the socket.
217 c2a03789 Iustin Pop

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

223 c2a03789 Iustin Pop
    """
224 c2a03789 Iustin Pop
    self._CheckSocket()
225 c2a03789 Iustin Pop
    etime = time.time() + self._rwtimeout
226 c2a03789 Iustin Pop
    while not self._msgs:
227 c2a03789 Iustin Pop
      if time.time() > etime:
228 c2a03789 Iustin Pop
        raise TimeoutError("Extended receive timeout")
229 6096ee13 Michael Hanselmann
      while True:
230 6096ee13 Michael Hanselmann
        try:
231 6096ee13 Michael Hanselmann
          data = self.socket.recv(4096)
232 6096ee13 Michael Hanselmann
        except socket.error, err:
233 6096ee13 Michael Hanselmann
          if err.args and err.args[0] == errno.EAGAIN:
234 6096ee13 Michael Hanselmann
            continue
235 6096ee13 Michael Hanselmann
          raise
236 6096ee13 Michael Hanselmann
        except socket.timeout, err:
237 6096ee13 Michael Hanselmann
          raise TimeoutError("Receive timeout: %s" % str(err))
238 6096ee13 Michael Hanselmann
        break
239 c2a03789 Iustin Pop
      if not data:
240 c2a03789 Iustin Pop
        raise ConnectionClosedError("Connection closed while reading")
241 c2a03789 Iustin Pop
      new_msgs = (self._buffer + data).split(self.eom)
242 c2a03789 Iustin Pop
      self._buffer = new_msgs.pop()
243 c2a03789 Iustin Pop
      self._msgs.extend(new_msgs)
244 c2a03789 Iustin Pop
    return self._msgs.popleft()
245 c2a03789 Iustin Pop
246 c2a03789 Iustin Pop
  def Call(self, msg):
247 c2a03789 Iustin Pop
    """Send a message and wait for the response.
248 c2a03789 Iustin Pop

249 c2a03789 Iustin Pop
    This is just a wrapper over Send and Recv.
250 c2a03789 Iustin Pop

251 c2a03789 Iustin Pop
    """
252 c2a03789 Iustin Pop
    self.Send(msg)
253 c2a03789 Iustin Pop
    return self.Recv()
254 c2a03789 Iustin Pop
255 c2a03789 Iustin Pop
  def Close(self):
256 c2a03789 Iustin Pop
    """Close the socket"""
257 c2a03789 Iustin Pop
    if self.socket is not None:
258 c2a03789 Iustin Pop
      self.socket.close()
259 c2a03789 Iustin Pop
      self.socket = None
260 c2a03789 Iustin Pop
261 c2a03789 Iustin Pop
262 c2a03789 Iustin Pop
class Client(object):
263 c2a03789 Iustin Pop
  """High-level client implementation.
264 c2a03789 Iustin Pop

265 c2a03789 Iustin Pop
  This uses a backing Transport-like class on top of which it
266 c2a03789 Iustin Pop
  implements data serialization/deserialization.
267 c2a03789 Iustin Pop

268 c2a03789 Iustin Pop
  """
269 ceab32dd Iustin Pop
  def __init__(self, address=None, timeouts=None, transport=Transport):
270 c2a03789 Iustin Pop
    """Constructor for the Client class.
271 c2a03789 Iustin Pop

272 c2a03789 Iustin Pop
    Arguments:
273 c2a03789 Iustin Pop
      - address: a valid address the the used transport class
274 c2a03789 Iustin Pop
      - timeout: a list of timeouts, to be used on connect and read/write
275 c2a03789 Iustin Pop
      - transport: a Transport-like class
276 c2a03789 Iustin Pop

277 c2a03789 Iustin Pop

278 c2a03789 Iustin Pop
    If timeout is not passed, the default timeouts of the transport
279 c2a03789 Iustin Pop
    class are used.
280 c2a03789 Iustin Pop

281 c2a03789 Iustin Pop
    """
282 ceab32dd Iustin Pop
    if address is None:
283 ceab32dd Iustin Pop
      address = constants.MASTER_SOCKET
284 8d5b316c Iustin Pop
    self.address = address
285 8d5b316c Iustin Pop
    self.timeouts = timeouts
286 8d5b316c Iustin Pop
    self.transport_class = transport
287 8d5b316c Iustin Pop
    self.transport = None
288 8d5b316c Iustin Pop
    self._InitTransport()
289 8d5b316c Iustin Pop
290 8d5b316c Iustin Pop
  def _InitTransport(self):
291 8d5b316c Iustin Pop
    """(Re)initialize the transport if needed.
292 8d5b316c Iustin Pop

293 8d5b316c Iustin Pop
    """
294 8d5b316c Iustin Pop
    if self.transport is None:
295 8d5b316c Iustin Pop
      self.transport = self.transport_class(self.address,
296 8d5b316c Iustin Pop
                                            timeouts=self.timeouts)
297 8d5b316c Iustin Pop
298 8d5b316c Iustin Pop
  def _CloseTransport(self):
299 8d5b316c Iustin Pop
    """Close the transport, ignoring errors.
300 8d5b316c Iustin Pop

301 8d5b316c Iustin Pop
    """
302 8d5b316c Iustin Pop
    if self.transport is None:
303 8d5b316c Iustin Pop
      return
304 8d5b316c Iustin Pop
    try:
305 8d5b316c Iustin Pop
      old_transp = self.transport
306 8d5b316c Iustin Pop
      self.transport = None
307 8d5b316c Iustin Pop
      old_transp.Close()
308 7260cfbe Iustin Pop
    except Exception: # pylint: disable-msg=W0703
309 8d5b316c Iustin Pop
      pass
310 c2a03789 Iustin Pop
311 3d8548c4 Michael Hanselmann
  def CallMethod(self, method, args):
312 c2a03789 Iustin Pop
    """Send a generic request and return the response.
313 c2a03789 Iustin Pop

314 c2a03789 Iustin Pop
    """
315 3d8548c4 Michael Hanselmann
    # Build request
316 3d8548c4 Michael Hanselmann
    request = {
317 3d8548c4 Michael Hanselmann
      KEY_METHOD: method,
318 3d8548c4 Michael Hanselmann
      KEY_ARGS: args,
319 3d8548c4 Michael Hanselmann
      }
320 3d8548c4 Michael Hanselmann
321 8d5b316c Iustin Pop
    # Serialize the request
322 8d5b316c Iustin Pop
    send_data = serializer.DumpJson(request, indent=False)
323 8d5b316c Iustin Pop
324 3d8548c4 Michael Hanselmann
    # Send request and wait for response
325 8d5b316c Iustin Pop
    try:
326 8d5b316c Iustin Pop
      self._InitTransport()
327 8d5b316c Iustin Pop
      result = self.transport.Call(send_data)
328 8d5b316c Iustin Pop
    except Exception:
329 8d5b316c Iustin Pop
      self._CloseTransport()
330 8d5b316c Iustin Pop
      raise
331 8d5b316c Iustin Pop
332 8d5b316c Iustin Pop
    # Parse the result
333 c2a03789 Iustin Pop
    try:
334 fad50141 Michael Hanselmann
      data = serializer.LoadJson(result)
335 c2a03789 Iustin Pop
    except Exception, err:
336 c2a03789 Iustin Pop
      raise ProtocolError("Error while deserializing response: %s" % str(err))
337 3d8548c4 Michael Hanselmann
338 3d8548c4 Michael Hanselmann
    # Validate response
339 a14a17fc Iustin Pop
    if (not isinstance(data, dict) or
340 3d8548c4 Michael Hanselmann
        KEY_SUCCESS not in data or
341 3d8548c4 Michael Hanselmann
        KEY_RESULT not in data):
342 a14a17fc Iustin Pop
      raise DecodingError("Invalid response from server: %s" % str(data))
343 3d8548c4 Michael Hanselmann
344 6797ec29 Iustin Pop
    result = data[KEY_RESULT]
345 6797ec29 Iustin Pop
346 3d8548c4 Michael Hanselmann
    if not data[KEY_SUCCESS]:
347 6956e9cd Iustin Pop
      errors.MaybeRaise(result)
348 6797ec29 Iustin Pop
      raise RequestError(result)
349 3d8548c4 Michael Hanselmann
350 6797ec29 Iustin Pop
    return result
351 c2a03789 Iustin Pop
352 3ccafd0e Iustin Pop
  def SetQueueDrainFlag(self, drain_flag):
353 3ccafd0e Iustin Pop
    return self.CallMethod(REQ_QUEUE_SET_DRAIN_FLAG, drain_flag)
354 3ccafd0e Iustin Pop
355 05e50653 Michael Hanselmann
  def SetWatcherPause(self, until):
356 05e50653 Michael Hanselmann
    return self.CallMethod(REQ_SET_WATCHER_PAUSE, [until])
357 05e50653 Michael Hanselmann
358 0bbe448c Michael Hanselmann
  def SubmitJob(self, ops):
359 0bbe448c Michael Hanselmann
    ops_state = map(lambda op: op.__getstate__(), ops)
360 0bbe448c Michael Hanselmann
    return self.CallMethod(REQ_SUBMIT_JOB, ops_state)
361 0bbe448c Michael Hanselmann
362 2971c913 Iustin Pop
  def SubmitManyJobs(self, jobs):
363 2971c913 Iustin Pop
    jobs_state = []
364 2971c913 Iustin Pop
    for ops in jobs:
365 2971c913 Iustin Pop
      jobs_state.append([op.__getstate__() for op in ops])
366 2971c913 Iustin Pop
    return self.CallMethod(REQ_SUBMIT_MANY_JOBS, jobs_state)
367 2971c913 Iustin Pop
368 0bbe448c Michael Hanselmann
  def CancelJob(self, job_id):
369 0bbe448c Michael Hanselmann
    return self.CallMethod(REQ_CANCEL_JOB, job_id)
370 0bbe448c Michael Hanselmann
371 0bbe448c Michael Hanselmann
  def ArchiveJob(self, job_id):
372 0bbe448c Michael Hanselmann
    return self.CallMethod(REQ_ARCHIVE_JOB, job_id)
373 0bbe448c Michael Hanselmann
374 07cd723a Iustin Pop
  def AutoArchiveJobs(self, age):
375 f8ad5591 Michael Hanselmann
    timeout = (DEF_RWTO - 1) / 2
376 f8ad5591 Michael Hanselmann
    return self.CallMethod(REQ_AUTOARCHIVE_JOBS, (age, timeout))
377 07cd723a Iustin Pop
378 f4484122 Michael Hanselmann
  def WaitForJobChangeOnce(self, job_id, fields,
379 793a8f7c Michael Hanselmann
                           prev_job_info, prev_log_serial,
380 793a8f7c Michael Hanselmann
                           timeout=WFJC_TIMEOUT):
381 793a8f7c Michael Hanselmann
    """Waits for changes on a job.
382 793a8f7c Michael Hanselmann

383 793a8f7c Michael Hanselmann
    @param job_id: Job ID
384 793a8f7c Michael Hanselmann
    @type fields: list
385 793a8f7c Michael Hanselmann
    @param fields: List of field names to be observed
386 793a8f7c Michael Hanselmann
    @type prev_job_info: None or list
387 793a8f7c Michael Hanselmann
    @param prev_job_info: Previously received job information
388 793a8f7c Michael Hanselmann
    @type prev_log_serial: None or int/long
389 793a8f7c Michael Hanselmann
    @param prev_log_serial: Highest log serial number previously received
390 793a8f7c Michael Hanselmann
    @type timeout: int/float
391 793a8f7c Michael Hanselmann
    @param timeout: Timeout in seconds (values larger than L{WFJC_TIMEOUT} will
392 793a8f7c Michael Hanselmann
                    be capped to that value)
393 793a8f7c Michael Hanselmann

394 793a8f7c Michael Hanselmann
    """
395 793a8f7c Michael Hanselmann
    assert timeout >= 0, "Timeout can not be negative"
396 f4484122 Michael Hanselmann
    return self.CallMethod(REQ_WAIT_FOR_JOB_CHANGE,
397 f4484122 Michael Hanselmann
                           (job_id, fields, prev_job_info,
398 793a8f7c Michael Hanselmann
                            prev_log_serial,
399 793a8f7c Michael Hanselmann
                            min(WFJC_TIMEOUT, timeout)))
400 f4484122 Michael Hanselmann
401 f4484122 Michael Hanselmann
  def WaitForJobChange(self, job_id, fields, prev_job_info, prev_log_serial):
402 5c735209 Iustin Pop
    while True:
403 f4484122 Michael Hanselmann
      result = self.WaitForJobChangeOnce(job_id, fields,
404 f4484122 Michael Hanselmann
                                         prev_job_info, prev_log_serial)
405 5c735209 Iustin Pop
      if result != constants.JOB_NOTCHANGED:
406 5c735209 Iustin Pop
        break
407 5c735209 Iustin Pop
    return result
408 dfe57c22 Michael Hanselmann
409 0bbe448c Michael Hanselmann
  def QueryJobs(self, job_ids, fields):
410 0bbe448c Michael Hanselmann
    return self.CallMethod(REQ_QUERY_JOBS, (job_ids, fields))
411 3d8548c4 Michael Hanselmann
412 ec79568d Iustin Pop
  def QueryInstances(self, names, fields, use_locking):
413 ec79568d Iustin Pop
    return self.CallMethod(REQ_QUERY_INSTANCES, (names, fields, use_locking))
414 ee6c7b94 Michael Hanselmann
415 ec79568d Iustin Pop
  def QueryNodes(self, names, fields, use_locking):
416 ec79568d Iustin Pop
    return self.CallMethod(REQ_QUERY_NODES, (names, fields, use_locking))
417 02f7fe54 Michael Hanselmann
418 ec79568d Iustin Pop
  def QueryExports(self, nodes, use_locking):
419 ec79568d Iustin Pop
    return self.CallMethod(REQ_QUERY_EXPORTS, (nodes, use_locking))
420 32f93223 Michael Hanselmann
421 66baeccc Iustin Pop
  def QueryClusterInfo(self):
422 66baeccc Iustin Pop
    return self.CallMethod(REQ_QUERY_CLUSTER_INFO, ())
423 66baeccc Iustin Pop
424 ae5849b5 Michael Hanselmann
  def QueryConfigValues(self, fields):
425 ae5849b5 Michael Hanselmann
    return self.CallMethod(REQ_QUERY_CONFIG_VALUES, fields)
426 ae5849b5 Michael Hanselmann
427 7699c3af Iustin Pop
  def QueryTags(self, kind, name):
428 7699c3af Iustin Pop
    return self.CallMethod(REQ_QUERY_TAGS, (kind, name))