Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / logic / rapi.py @ 9dcfad23

History | View | Annotate | Download (52.2 kB)

1 e5e20779 Faidon Liambotis
#
2 e5e20779 Faidon Liambotis
#
3 e5e20779 Faidon Liambotis
4 a3ad611d Dimitris Aragiorgis
# Copyright (C) 2010, 2011 Google Inc.
5 b4135a1b Christos Stavrakakis
# Copyright (C) 2013, GRNET S.A.
6 e5e20779 Faidon Liambotis
#
7 e5e20779 Faidon Liambotis
# This program is free software; you can redistribute it and/or modify
8 e5e20779 Faidon Liambotis
# it under the terms of the GNU General Public License as published by
9 e5e20779 Faidon Liambotis
# the Free Software Foundation; either version 2 of the License, or
10 e5e20779 Faidon Liambotis
# (at your option) any later version.
11 e5e20779 Faidon Liambotis
#
12 e5e20779 Faidon Liambotis
# This program is distributed in the hope that it will be useful, but
13 e5e20779 Faidon Liambotis
# WITHOUT ANY WARRANTY; without even the implied warranty of
14 e5e20779 Faidon Liambotis
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 e5e20779 Faidon Liambotis
# General Public License for more details.
16 e5e20779 Faidon Liambotis
#
17 e5e20779 Faidon Liambotis
# You should have received a copy of the GNU General Public License
18 e5e20779 Faidon Liambotis
# along with this program; if not, write to the Free Software
19 e5e20779 Faidon Liambotis
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 e5e20779 Faidon Liambotis
# 02110-1301, USA.
21 e5e20779 Faidon Liambotis
22 e5e20779 Faidon Liambotis
23 b4135a1b Christos Stavrakakis
"""Ganeti RAPI client."""
24 e5e20779 Faidon Liambotis
25 e5e20779 Faidon Liambotis
# No Ganeti-specific modules should be imported. The RAPI client is supposed to
26 e5e20779 Faidon Liambotis
# be standalone.
27 e5e20779 Faidon Liambotis
28 b4135a1b Christos Stavrakakis
import requests
29 9e98ba3c Giorgos Verigakis
import logging
30 a3ad611d Dimitris Aragiorgis
import simplejson
31 a3ad611d Dimitris Aragiorgis
import time
32 3481786b Faidon Liambotis
33 e5e20779 Faidon Liambotis
GANETI_RAPI_PORT = 5080
34 e5e20779 Faidon Liambotis
GANETI_RAPI_VERSION = 2
35 e5e20779 Faidon Liambotis
36 e5e20779 Faidon Liambotis
HTTP_DELETE = "DELETE"
37 e5e20779 Faidon Liambotis
HTTP_GET = "GET"
38 e5e20779 Faidon Liambotis
HTTP_PUT = "PUT"
39 e5e20779 Faidon Liambotis
HTTP_POST = "POST"
40 e5e20779 Faidon Liambotis
HTTP_OK = 200
41 e5e20779 Faidon Liambotis
HTTP_NOT_FOUND = 404
42 e5e20779 Faidon Liambotis
HTTP_APP_JSON = "application/json"
43 e5e20779 Faidon Liambotis
44 e5e20779 Faidon Liambotis
REPLACE_DISK_PRI = "replace_on_primary"
45 e5e20779 Faidon Liambotis
REPLACE_DISK_SECONDARY = "replace_on_secondary"
46 e5e20779 Faidon Liambotis
REPLACE_DISK_CHG = "replace_new_secondary"
47 e5e20779 Faidon Liambotis
REPLACE_DISK_AUTO = "replace_auto"
48 e5e20779 Faidon Liambotis
49 a3ad611d Dimitris Aragiorgis
NODE_EVAC_PRI = "primary-only"
50 a3ad611d Dimitris Aragiorgis
NODE_EVAC_SEC = "secondary-only"
51 a3ad611d Dimitris Aragiorgis
NODE_EVAC_ALL = "all"
52 a3ad611d Dimitris Aragiorgis
53 e5e20779 Faidon Liambotis
NODE_ROLE_DRAINED = "drained"
54 e5e20779 Faidon Liambotis
NODE_ROLE_MASTER_CANDIATE = "master-candidate"
55 e5e20779 Faidon Liambotis
NODE_ROLE_MASTER = "master"
56 e5e20779 Faidon Liambotis
NODE_ROLE_OFFLINE = "offline"
57 e5e20779 Faidon Liambotis
NODE_ROLE_REGULAR = "regular"
58 e5e20779 Faidon Liambotis
59 a3ad611d Dimitris Aragiorgis
JOB_STATUS_QUEUED = "queued"
60 a3ad611d Dimitris Aragiorgis
JOB_STATUS_WAITING = "waiting"
61 a3ad611d Dimitris Aragiorgis
JOB_STATUS_CANCELING = "canceling"
62 a3ad611d Dimitris Aragiorgis
JOB_STATUS_RUNNING = "running"
63 a3ad611d Dimitris Aragiorgis
JOB_STATUS_CANCELED = "canceled"
64 a3ad611d Dimitris Aragiorgis
JOB_STATUS_SUCCESS = "success"
65 a3ad611d Dimitris Aragiorgis
JOB_STATUS_ERROR = "error"
66 a3ad611d Dimitris Aragiorgis
JOB_STATUS_FINALIZED = frozenset([
67 a3ad611d Dimitris Aragiorgis
  JOB_STATUS_CANCELED,
68 a3ad611d Dimitris Aragiorgis
  JOB_STATUS_SUCCESS,
69 a3ad611d Dimitris Aragiorgis
  JOB_STATUS_ERROR,
70 a3ad611d Dimitris Aragiorgis
  ])
71 a3ad611d Dimitris Aragiorgis
JOB_STATUS_ALL = frozenset([
72 a3ad611d Dimitris Aragiorgis
  JOB_STATUS_QUEUED,
73 a3ad611d Dimitris Aragiorgis
  JOB_STATUS_WAITING,
74 a3ad611d Dimitris Aragiorgis
  JOB_STATUS_CANCELING,
75 a3ad611d Dimitris Aragiorgis
  JOB_STATUS_RUNNING,
76 a3ad611d Dimitris Aragiorgis
  ]) | JOB_STATUS_FINALIZED
77 a3ad611d Dimitris Aragiorgis
78 a3ad611d Dimitris Aragiorgis
# Legacy name
79 a3ad611d Dimitris Aragiorgis
JOB_STATUS_WAITLOCK = JOB_STATUS_WAITING
80 a3ad611d Dimitris Aragiorgis
81 e5e20779 Faidon Liambotis
# Internal constants
82 e5e20779 Faidon Liambotis
_REQ_DATA_VERSION_FIELD = "__version__"
83 a3ad611d Dimitris Aragiorgis
_QPARAM_DRY_RUN = "dry-run"
84 a3ad611d Dimitris Aragiorgis
_QPARAM_FORCE = "force"
85 a3ad611d Dimitris Aragiorgis
86 a3ad611d Dimitris Aragiorgis
# Feature strings
87 a3ad611d Dimitris Aragiorgis
INST_CREATE_REQV1 = "instance-create-reqv1"
88 a3ad611d Dimitris Aragiorgis
INST_REINSTALL_REQV1 = "instance-reinstall-reqv1"
89 a3ad611d Dimitris Aragiorgis
NODE_MIGRATE_REQV1 = "node-migrate-reqv1"
90 a3ad611d Dimitris Aragiorgis
NODE_EVAC_RES1 = "node-evac-res1"
91 a3ad611d Dimitris Aragiorgis
92 a3ad611d Dimitris Aragiorgis
# Old feature constant names in case they're references by users of this module
93 a3ad611d Dimitris Aragiorgis
_INST_CREATE_REQV1 = INST_CREATE_REQV1
94 a3ad611d Dimitris Aragiorgis
_INST_REINSTALL_REQV1 = INST_REINSTALL_REQV1
95 a3ad611d Dimitris Aragiorgis
_NODE_MIGRATE_REQV1 = NODE_MIGRATE_REQV1
96 a3ad611d Dimitris Aragiorgis
_NODE_EVAC_RES1 = NODE_EVAC_RES1
97 e5e20779 Faidon Liambotis
98 e5e20779 Faidon Liambotis
99 e5e20779 Faidon Liambotis
100 e5e20779 Faidon Liambotis
class Error(Exception):
101 e5e20779 Faidon Liambotis
  """Base error class for this module.
102 e5e20779 Faidon Liambotis

103 e5e20779 Faidon Liambotis
  """
104 e5e20779 Faidon Liambotis
  pass
105 e5e20779 Faidon Liambotis
106 e5e20779 Faidon Liambotis
107 a3ad611d Dimitris Aragiorgis
class GanetiApiError(Error):
108 a3ad611d Dimitris Aragiorgis
  """Generic error raised from Ganeti API.
109 a3ad611d Dimitris Aragiorgis

110 a3ad611d Dimitris Aragiorgis
  """
111 a3ad611d Dimitris Aragiorgis
  def __init__(self, msg, code=None):
112 a3ad611d Dimitris Aragiorgis
    Error.__init__(self, msg)
113 a3ad611d Dimitris Aragiorgis
    self.code = code
114 a3ad611d Dimitris Aragiorgis
115 a3ad611d Dimitris Aragiorgis
116 a3ad611d Dimitris Aragiorgis
class CertificateError(GanetiApiError):
117 e5e20779 Faidon Liambotis
  """Raised when a problem is found with the SSL certificate.
118 e5e20779 Faidon Liambotis

119 e5e20779 Faidon Liambotis
  """
120 e5e20779 Faidon Liambotis
  pass
121 e5e20779 Faidon Liambotis
122 e5e20779 Faidon Liambotis
123 a3ad611d Dimitris Aragiorgis
def _AppendIf(container, condition, value):
124 a3ad611d Dimitris Aragiorgis
  """Appends to a list if a condition evaluates to truth.
125 e5e20779 Faidon Liambotis

126 e5e20779 Faidon Liambotis
  """
127 a3ad611d Dimitris Aragiorgis
  if condition:
128 a3ad611d Dimitris Aragiorgis
    container.append(value)
129 a3ad611d Dimitris Aragiorgis
130 a3ad611d Dimitris Aragiorgis
  return condition
131 a3ad611d Dimitris Aragiorgis
132 a3ad611d Dimitris Aragiorgis
133 a3ad611d Dimitris Aragiorgis
def _AppendDryRunIf(container, condition):
134 a3ad611d Dimitris Aragiorgis
  """Appends a "dry-run" parameter if a condition evaluates to truth.
135 a3ad611d Dimitris Aragiorgis

136 a3ad611d Dimitris Aragiorgis
  """
137 a3ad611d Dimitris Aragiorgis
  return _AppendIf(container, condition, (_QPARAM_DRY_RUN, 1))
138 a3ad611d Dimitris Aragiorgis
139 a3ad611d Dimitris Aragiorgis
140 a3ad611d Dimitris Aragiorgis
def _AppendForceIf(container, condition):
141 a3ad611d Dimitris Aragiorgis
  """Appends a "force" parameter if a condition evaluates to truth.
142 a3ad611d Dimitris Aragiorgis

143 a3ad611d Dimitris Aragiorgis
  """
144 a3ad611d Dimitris Aragiorgis
  return _AppendIf(container, condition, (_QPARAM_FORCE, 1))
145 a3ad611d Dimitris Aragiorgis
146 a3ad611d Dimitris Aragiorgis
147 a3ad611d Dimitris Aragiorgis
def _SetItemIf(container, condition, item, value):
148 a3ad611d Dimitris Aragiorgis
  """Sets an item if a condition evaluates to truth.
149 a3ad611d Dimitris Aragiorgis

150 a3ad611d Dimitris Aragiorgis
  """
151 a3ad611d Dimitris Aragiorgis
  if condition:
152 a3ad611d Dimitris Aragiorgis
    container[item] = value
153 a3ad611d Dimitris Aragiorgis
154 a3ad611d Dimitris Aragiorgis
  return condition
155 e5e20779 Faidon Liambotis
156 e5e20779 Faidon Liambotis
157 a3ad611d Dimitris Aragiorgis
class GanetiRapiClient(object): # pylint: disable=R0904
158 e5e20779 Faidon Liambotis
  """Ganeti RAPI client.
159 e5e20779 Faidon Liambotis

160 e5e20779 Faidon Liambotis
  """
161 e5e20779 Faidon Liambotis
  USER_AGENT = "Ganeti RAPI Client"
162 a3ad611d Dimitris Aragiorgis
  _json_encoder = simplejson.JSONEncoder(sort_keys=True)
163 e5e20779 Faidon Liambotis
164 e5e20779 Faidon Liambotis
  def __init__(self, host, port=GANETI_RAPI_PORT,
165 b4135a1b Christos Stavrakakis
               username=None, password=None, logger=logging):
166 e5e20779 Faidon Liambotis
    """Initializes this class.
167 e5e20779 Faidon Liambotis

168 e5e20779 Faidon Liambotis
    @type host: string
169 e5e20779 Faidon Liambotis
    @param host: the ganeti cluster master to interact with
170 e5e20779 Faidon Liambotis
    @type port: int
171 e5e20779 Faidon Liambotis
    @param port: the port on which the RAPI is running (default is 5080)
172 e5e20779 Faidon Liambotis
    @type username: string
173 e5e20779 Faidon Liambotis
    @param username: the username to connect with
174 e5e20779 Faidon Liambotis
    @type password: string
175 e5e20779 Faidon Liambotis
    @param password: the password to connect with
176 e5e20779 Faidon Liambotis
    @param logger: Logging object
177 e5e20779 Faidon Liambotis

178 e5e20779 Faidon Liambotis
    """
179 e5e20779 Faidon Liambotis
    self._logger = logger
180 b4135a1b Christos Stavrakakis
    self._base_url = "https://%s:%s" % (host, port)
181 e5e20779 Faidon Liambotis
182 e5e20779 Faidon Liambotis
    if username is not None:
183 e5e20779 Faidon Liambotis
      if password is None:
184 e5e20779 Faidon Liambotis
        raise Error("Password not specified")
185 e5e20779 Faidon Liambotis
    elif password:
186 e5e20779 Faidon Liambotis
      raise Error("Specified password without username")
187 e5e20779 Faidon Liambotis
188 b4135a1b Christos Stavrakakis
    self._auth = (username, password)
189 e5e20779 Faidon Liambotis
190 e5e20779 Faidon Liambotis
  def _SendRequest(self, method, path, query, content):
191 e5e20779 Faidon Liambotis
    """Sends an HTTP request.
192 e5e20779 Faidon Liambotis

193 e5e20779 Faidon Liambotis
    This constructs a full URL, encodes and decodes HTTP bodies, and
194 e5e20779 Faidon Liambotis
    handles invalid responses in a pythonic way.
195 e5e20779 Faidon Liambotis

196 e5e20779 Faidon Liambotis
    @type method: string
197 e5e20779 Faidon Liambotis
    @param method: HTTP method to use
198 e5e20779 Faidon Liambotis
    @type path: string
199 e5e20779 Faidon Liambotis
    @param path: HTTP URL path
200 e5e20779 Faidon Liambotis
    @type query: list of two-tuples
201 e5e20779 Faidon Liambotis
    @param query: query arguments to pass to urllib.urlencode
202 e5e20779 Faidon Liambotis
    @type content: str or None
203 e5e20779 Faidon Liambotis
    @param content: HTTP body content
204 e5e20779 Faidon Liambotis

205 e5e20779 Faidon Liambotis
    @rtype: str
206 e5e20779 Faidon Liambotis
    @return: JSON-Decoded response
207 e5e20779 Faidon Liambotis

208 e5e20779 Faidon Liambotis
    @raises CertificateError: If an invalid SSL certificate is found
209 e5e20779 Faidon Liambotis
    @raises GanetiApiError: If an invalid response is returned
210 e5e20779 Faidon Liambotis

211 e5e20779 Faidon Liambotis
    """
212 e5e20779 Faidon Liambotis
    assert path.startswith("/")
213 b4135a1b Christos Stavrakakis
    url = "%s%s" % (self._base_url, path)
214 e5e20779 Faidon Liambotis
215 b4135a1b Christos Stavrakakis
    headers = {}
216 e5e20779 Faidon Liambotis
    if content is not None:
217 e5e20779 Faidon Liambotis
      encoded_content = self._json_encoder.encode(content)
218 b4135a1b Christos Stavrakakis
      headers = {"content-type": HTTP_APP_JSON,
219 b4135a1b Christos Stavrakakis
                 "accept": HTTP_APP_JSON}
220 e5e20779 Faidon Liambotis
    else:
221 e5e20779 Faidon Liambotis
      encoded_content = ""
222 e5e20779 Faidon Liambotis
223 b4135a1b Christos Stavrakakis
    if query is not None:
224 b4135a1b Christos Stavrakakis
        query = dict(query)
225 b4135a1b Christos Stavrakakis
226 b4135a1b Christos Stavrakakis
    self._logger.debug("Sending request %s %s (query=%r) (content=%r)",
227 b4135a1b Christos Stavrakakis
                       method, url, query, encoded_content)
228 b4135a1b Christos Stavrakakis
229 b4135a1b Christos Stavrakakis
    req_method = getattr(requests, method.lower())
230 b4135a1b Christos Stavrakakis
    r = req_method(url, auth=self._auth, headers=headers, params=query,
231 b4135a1b Christos Stavrakakis
                   data=encoded_content, verify=False)
232 b4135a1b Christos Stavrakakis
233 b4135a1b Christos Stavrakakis
234 b4135a1b Christos Stavrakakis
    http_code = r.status_code
235 b4135a1b Christos Stavrakakis
    if r.content is not None:
236 b4135a1b Christos Stavrakakis
        response_content = simplejson.loads(r.content)
237 e5e20779 Faidon Liambotis
    else:
238 b4135a1b Christos Stavrakakis
        response_content = None
239 e5e20779 Faidon Liambotis
240 e5e20779 Faidon Liambotis
    if http_code != HTTP_OK:
241 e5e20779 Faidon Liambotis
      if isinstance(response_content, dict):
242 e5e20779 Faidon Liambotis
        msg = ("%s %s: %s" %
243 e5e20779 Faidon Liambotis
               (response_content["code"],
244 e5e20779 Faidon Liambotis
                response_content["message"],
245 e5e20779 Faidon Liambotis
                response_content["explain"]))
246 e5e20779 Faidon Liambotis
      else:
247 e5e20779 Faidon Liambotis
        msg = str(response_content)
248 e5e20779 Faidon Liambotis
249 e5e20779 Faidon Liambotis
      raise GanetiApiError(msg, code=http_code)
250 e5e20779 Faidon Liambotis
251 e5e20779 Faidon Liambotis
    return response_content
252 e5e20779 Faidon Liambotis
253 e5e20779 Faidon Liambotis
  def GetVersion(self):
254 e5e20779 Faidon Liambotis
    """Gets the Remote API version running on the cluster.
255 e5e20779 Faidon Liambotis

256 e5e20779 Faidon Liambotis
    @rtype: int
257 e5e20779 Faidon Liambotis
    @return: Ganeti Remote API version
258 e5e20779 Faidon Liambotis

259 e5e20779 Faidon Liambotis
    """
260 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_GET, "/version", None, None)
261 e5e20779 Faidon Liambotis
262 e5e20779 Faidon Liambotis
  def GetFeatures(self):
263 e5e20779 Faidon Liambotis
    """Gets the list of optional features supported by RAPI server.
264 e5e20779 Faidon Liambotis

265 e5e20779 Faidon Liambotis
    @rtype: list
266 e5e20779 Faidon Liambotis
    @return: List of optional features
267 e5e20779 Faidon Liambotis

268 e5e20779 Faidon Liambotis
    """
269 e5e20779 Faidon Liambotis
    try:
270 e5e20779 Faidon Liambotis
      return self._SendRequest(HTTP_GET, "/%s/features" % GANETI_RAPI_VERSION,
271 e5e20779 Faidon Liambotis
                               None, None)
272 e5e20779 Faidon Liambotis
    except GanetiApiError, err:
273 e5e20779 Faidon Liambotis
      # Older RAPI servers don't support this resource
274 e5e20779 Faidon Liambotis
      if err.code == HTTP_NOT_FOUND:
275 e5e20779 Faidon Liambotis
        return []
276 e5e20779 Faidon Liambotis
277 e5e20779 Faidon Liambotis
      raise
278 e5e20779 Faidon Liambotis
279 e5e20779 Faidon Liambotis
  def GetOperatingSystems(self):
280 e5e20779 Faidon Liambotis
    """Gets the Operating Systems running in the Ganeti cluster.
281 e5e20779 Faidon Liambotis

282 e5e20779 Faidon Liambotis
    @rtype: list of str
283 e5e20779 Faidon Liambotis
    @return: operating systems
284 e5e20779 Faidon Liambotis

285 e5e20779 Faidon Liambotis
    """
286 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_GET, "/%s/os" % GANETI_RAPI_VERSION,
287 e5e20779 Faidon Liambotis
                             None, None)
288 e5e20779 Faidon Liambotis
289 e5e20779 Faidon Liambotis
  def GetInfo(self):
290 e5e20779 Faidon Liambotis
    """Gets info about the cluster.
291 e5e20779 Faidon Liambotis

292 e5e20779 Faidon Liambotis
    @rtype: dict
293 e5e20779 Faidon Liambotis
    @return: information about the cluster
294 e5e20779 Faidon Liambotis

295 e5e20779 Faidon Liambotis
    """
296 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_GET, "/%s/info" % GANETI_RAPI_VERSION,
297 e5e20779 Faidon Liambotis
                             None, None)
298 e5e20779 Faidon Liambotis
299 067dda99 Vangelis Koukis
  def RedistributeConfig(self):
300 067dda99 Vangelis Koukis
    """Tells the cluster to redistribute its configuration files.
301 067dda99 Vangelis Koukis

302 a3ad611d Dimitris Aragiorgis
    @rtype: string
303 067dda99 Vangelis Koukis
    @return: job id
304 067dda99 Vangelis Koukis

305 067dda99 Vangelis Koukis
    """
306 067dda99 Vangelis Koukis
    return self._SendRequest(HTTP_PUT,
307 067dda99 Vangelis Koukis
                             "/%s/redistribute-config" % GANETI_RAPI_VERSION,
308 067dda99 Vangelis Koukis
                             None, None)
309 067dda99 Vangelis Koukis
310 067dda99 Vangelis Koukis
  def ModifyCluster(self, **kwargs):
311 067dda99 Vangelis Koukis
    """Modifies cluster parameters.
312 067dda99 Vangelis Koukis

313 067dda99 Vangelis Koukis
    More details for parameters can be found in the RAPI documentation.
314 067dda99 Vangelis Koukis

315 a3ad611d Dimitris Aragiorgis
    @rtype: string
316 067dda99 Vangelis Koukis
    @return: job id
317 067dda99 Vangelis Koukis

318 067dda99 Vangelis Koukis
    """
319 067dda99 Vangelis Koukis
    body = kwargs
320 067dda99 Vangelis Koukis
321 067dda99 Vangelis Koukis
    return self._SendRequest(HTTP_PUT,
322 067dda99 Vangelis Koukis
                             "/%s/modify" % GANETI_RAPI_VERSION, None, body)
323 067dda99 Vangelis Koukis
324 e5e20779 Faidon Liambotis
  def GetClusterTags(self):
325 e5e20779 Faidon Liambotis
    """Gets the cluster tags.
326 e5e20779 Faidon Liambotis

327 e5e20779 Faidon Liambotis
    @rtype: list of str
328 e5e20779 Faidon Liambotis
    @return: cluster tags
329 e5e20779 Faidon Liambotis

330 e5e20779 Faidon Liambotis
    """
331 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_GET, "/%s/tags" % GANETI_RAPI_VERSION,
332 e5e20779 Faidon Liambotis
                             None, None)
333 e5e20779 Faidon Liambotis
334 e5e20779 Faidon Liambotis
  def AddClusterTags(self, tags, dry_run=False):
335 e5e20779 Faidon Liambotis
    """Adds tags to the cluster.
336 e5e20779 Faidon Liambotis

337 e5e20779 Faidon Liambotis
    @type tags: list of str
338 e5e20779 Faidon Liambotis
    @param tags: tags to add to the cluster
339 e5e20779 Faidon Liambotis
    @type dry_run: bool
340 e5e20779 Faidon Liambotis
    @param dry_run: whether to perform a dry run
341 e5e20779 Faidon Liambotis

342 a3ad611d Dimitris Aragiorgis
    @rtype: string
343 e5e20779 Faidon Liambotis
    @return: job id
344 e5e20779 Faidon Liambotis

345 e5e20779 Faidon Liambotis
    """
346 e5e20779 Faidon Liambotis
    query = [("tag", t) for t in tags]
347 a3ad611d Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
348 e5e20779 Faidon Liambotis
349 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_PUT, "/%s/tags" % GANETI_RAPI_VERSION,
350 e5e20779 Faidon Liambotis
                             query, None)
351 e5e20779 Faidon Liambotis
352 e5e20779 Faidon Liambotis
  def DeleteClusterTags(self, tags, dry_run=False):
353 e5e20779 Faidon Liambotis
    """Deletes tags from the cluster.
354 e5e20779 Faidon Liambotis

355 e5e20779 Faidon Liambotis
    @type tags: list of str
356 e5e20779 Faidon Liambotis
    @param tags: tags to delete
357 e5e20779 Faidon Liambotis
    @type dry_run: bool
358 e5e20779 Faidon Liambotis
    @param dry_run: whether to perform a dry run
359 a3ad611d Dimitris Aragiorgis
    @rtype: string
360 a3ad611d Dimitris Aragiorgis
    @return: job id
361 e5e20779 Faidon Liambotis

362 e5e20779 Faidon Liambotis
    """
363 e5e20779 Faidon Liambotis
    query = [("tag", t) for t in tags]
364 a3ad611d Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
365 e5e20779 Faidon Liambotis
366 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_DELETE, "/%s/tags" % GANETI_RAPI_VERSION,
367 e5e20779 Faidon Liambotis
                             query, None)
368 e5e20779 Faidon Liambotis
369 e5e20779 Faidon Liambotis
  def GetInstances(self, bulk=False):
370 e5e20779 Faidon Liambotis
    """Gets information about instances on the cluster.
371 e5e20779 Faidon Liambotis

372 e5e20779 Faidon Liambotis
    @type bulk: bool
373 e5e20779 Faidon Liambotis
    @param bulk: whether to return all information about all instances
374 e5e20779 Faidon Liambotis

375 e5e20779 Faidon Liambotis
    @rtype: list of dict or list of str
376 e5e20779 Faidon Liambotis
    @return: if bulk is True, info about the instances, else a list of instances
377 e5e20779 Faidon Liambotis

378 e5e20779 Faidon Liambotis
    """
379 e5e20779 Faidon Liambotis
    query = []
380 a3ad611d Dimitris Aragiorgis
    _AppendIf(query, bulk, ("bulk", 1))
381 e5e20779 Faidon Liambotis
382 e5e20779 Faidon Liambotis
    instances = self._SendRequest(HTTP_GET,
383 e5e20779 Faidon Liambotis
                                  "/%s/instances" % GANETI_RAPI_VERSION,
384 e5e20779 Faidon Liambotis
                                  query, None)
385 e5e20779 Faidon Liambotis
    if bulk:
386 e5e20779 Faidon Liambotis
      return instances
387 e5e20779 Faidon Liambotis
    else:
388 e5e20779 Faidon Liambotis
      return [i["id"] for i in instances]
389 e5e20779 Faidon Liambotis
390 e5e20779 Faidon Liambotis
  def GetInstance(self, instance):
391 e5e20779 Faidon Liambotis
    """Gets information about an instance.
392 e5e20779 Faidon Liambotis

393 e5e20779 Faidon Liambotis
    @type instance: str
394 e5e20779 Faidon Liambotis
    @param instance: instance whose info to return
395 e5e20779 Faidon Liambotis

396 e5e20779 Faidon Liambotis
    @rtype: dict
397 e5e20779 Faidon Liambotis
    @return: info about the instance
398 e5e20779 Faidon Liambotis

399 e5e20779 Faidon Liambotis
    """
400 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_GET,
401 e5e20779 Faidon Liambotis
                             ("/%s/instances/%s" %
402 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, instance)), None, None)
403 e5e20779 Faidon Liambotis
404 e5e20779 Faidon Liambotis
  def GetInstanceInfo(self, instance, static=None):
405 e5e20779 Faidon Liambotis
    """Gets information about an instance.
406 e5e20779 Faidon Liambotis

407 e5e20779 Faidon Liambotis
    @type instance: string
408 e5e20779 Faidon Liambotis
    @param instance: Instance name
409 e5e20779 Faidon Liambotis
    @rtype: string
410 e5e20779 Faidon Liambotis
    @return: Job ID
411 e5e20779 Faidon Liambotis

412 e5e20779 Faidon Liambotis
    """
413 e5e20779 Faidon Liambotis
    if static is not None:
414 e5e20779 Faidon Liambotis
      query = [("static", static)]
415 e5e20779 Faidon Liambotis
    else:
416 e5e20779 Faidon Liambotis
      query = None
417 e5e20779 Faidon Liambotis
418 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_GET,
419 e5e20779 Faidon Liambotis
                             ("/%s/instances/%s/info" %
420 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, instance)), query, None)
421 e5e20779 Faidon Liambotis
422 e5e20779 Faidon Liambotis
  def CreateInstance(self, mode, name, disk_template, disks, nics,
423 e5e20779 Faidon Liambotis
                     **kwargs):
424 e5e20779 Faidon Liambotis
    """Creates a new instance.
425 e5e20779 Faidon Liambotis

426 e5e20779 Faidon Liambotis
    More details for parameters can be found in the RAPI documentation.
427 e5e20779 Faidon Liambotis

428 e5e20779 Faidon Liambotis
    @type mode: string
429 e5e20779 Faidon Liambotis
    @param mode: Instance creation mode
430 e5e20779 Faidon Liambotis
    @type name: string
431 e5e20779 Faidon Liambotis
    @param name: Hostname of the instance to create
432 e5e20779 Faidon Liambotis
    @type disk_template: string
433 e5e20779 Faidon Liambotis
    @param disk_template: Disk template for instance (e.g. plain, diskless,
434 e5e20779 Faidon Liambotis
                          file, or drbd)
435 e5e20779 Faidon Liambotis
    @type disks: list of dicts
436 e5e20779 Faidon Liambotis
    @param disks: List of disk definitions
437 e5e20779 Faidon Liambotis
    @type nics: list of dicts
438 e5e20779 Faidon Liambotis
    @param nics: List of NIC definitions
439 e5e20779 Faidon Liambotis
    @type dry_run: bool
440 e5e20779 Faidon Liambotis
    @keyword dry_run: whether to perform a dry run
441 e5e20779 Faidon Liambotis

442 a3ad611d Dimitris Aragiorgis
    @rtype: string
443 e5e20779 Faidon Liambotis
    @return: job id
444 e5e20779 Faidon Liambotis

445 e5e20779 Faidon Liambotis
    """
446 e5e20779 Faidon Liambotis
    query = []
447 e5e20779 Faidon Liambotis
448 a3ad611d Dimitris Aragiorgis
    _AppendDryRunIf(query, kwargs.get("dry_run"))
449 e5e20779 Faidon Liambotis
450 e5e20779 Faidon Liambotis
    if _INST_CREATE_REQV1 in self.GetFeatures():
451 e5e20779 Faidon Liambotis
      # All required fields for request data version 1
452 e5e20779 Faidon Liambotis
      body = {
453 e5e20779 Faidon Liambotis
        _REQ_DATA_VERSION_FIELD: 1,
454 e5e20779 Faidon Liambotis
        "mode": mode,
455 e5e20779 Faidon Liambotis
        "name": name,
456 e5e20779 Faidon Liambotis
        "disk_template": disk_template,
457 e5e20779 Faidon Liambotis
        "disks": disks,
458 e5e20779 Faidon Liambotis
        "nics": nics,
459 e5e20779 Faidon Liambotis
        }
460 e5e20779 Faidon Liambotis
461 e5e20779 Faidon Liambotis
      conflicts = set(kwargs.iterkeys()) & set(body.iterkeys())
462 e5e20779 Faidon Liambotis
      if conflicts:
463 e5e20779 Faidon Liambotis
        raise GanetiApiError("Required fields can not be specified as"
464 e5e20779 Faidon Liambotis
                             " keywords: %s" % ", ".join(conflicts))
465 e5e20779 Faidon Liambotis
466 e5e20779 Faidon Liambotis
      body.update((key, value) for key, value in kwargs.iteritems()
467 e5e20779 Faidon Liambotis
                  if key != "dry_run")
468 e5e20779 Faidon Liambotis
    else:
469 a3ad611d Dimitris Aragiorgis
      raise GanetiApiError("Server does not support new-style (version 1)"
470 a3ad611d Dimitris Aragiorgis
                           " instance creation requests")
471 e5e20779 Faidon Liambotis
472 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_POST, "/%s/instances" % GANETI_RAPI_VERSION,
473 e5e20779 Faidon Liambotis
                             query, body)
474 e5e20779 Faidon Liambotis
475 e5e20779 Faidon Liambotis
  def DeleteInstance(self, instance, dry_run=False):
476 e5e20779 Faidon Liambotis
    """Deletes an instance.
477 e5e20779 Faidon Liambotis

478 e5e20779 Faidon Liambotis
    @type instance: str
479 e5e20779 Faidon Liambotis
    @param instance: the instance to delete
480 e5e20779 Faidon Liambotis

481 a3ad611d Dimitris Aragiorgis
    @rtype: string
482 e5e20779 Faidon Liambotis
    @return: job id
483 e5e20779 Faidon Liambotis

484 e5e20779 Faidon Liambotis
    """
485 e5e20779 Faidon Liambotis
    query = []
486 a3ad611d Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
487 e5e20779 Faidon Liambotis
488 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_DELETE,
489 e5e20779 Faidon Liambotis
                             ("/%s/instances/%s" %
490 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, instance)), query, None)
491 e5e20779 Faidon Liambotis
492 e5e20779 Faidon Liambotis
  def ModifyInstance(self, instance, **kwargs):
493 e5e20779 Faidon Liambotis
    """Modifies an instance.
494 e5e20779 Faidon Liambotis

495 e5e20779 Faidon Liambotis
    More details for parameters can be found in the RAPI documentation.
496 e5e20779 Faidon Liambotis

497 e5e20779 Faidon Liambotis
    @type instance: string
498 e5e20779 Faidon Liambotis
    @param instance: Instance name
499 a3ad611d Dimitris Aragiorgis
    @rtype: string
500 e5e20779 Faidon Liambotis
    @return: job id
501 e5e20779 Faidon Liambotis

502 e5e20779 Faidon Liambotis
    """
503 e5e20779 Faidon Liambotis
    body = kwargs
504 e5e20779 Faidon Liambotis
505 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_PUT,
506 e5e20779 Faidon Liambotis
                             ("/%s/instances/%s/modify" %
507 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, instance)), None, body)
508 e5e20779 Faidon Liambotis
509 067dda99 Vangelis Koukis
  def ActivateInstanceDisks(self, instance, ignore_size=None):
510 067dda99 Vangelis Koukis
    """Activates an instance's disks.
511 067dda99 Vangelis Koukis

512 067dda99 Vangelis Koukis
    @type instance: string
513 067dda99 Vangelis Koukis
    @param instance: Instance name
514 067dda99 Vangelis Koukis
    @type ignore_size: bool
515 067dda99 Vangelis Koukis
    @param ignore_size: Whether to ignore recorded size
516 a3ad611d Dimitris Aragiorgis
    @rtype: string
517 067dda99 Vangelis Koukis
    @return: job id
518 067dda99 Vangelis Koukis

519 067dda99 Vangelis Koukis
    """
520 067dda99 Vangelis Koukis
    query = []
521 a3ad611d Dimitris Aragiorgis
    _AppendIf(query, ignore_size, ("ignore_size", 1))
522 067dda99 Vangelis Koukis
523 067dda99 Vangelis Koukis
    return self._SendRequest(HTTP_PUT,
524 067dda99 Vangelis Koukis
                             ("/%s/instances/%s/activate-disks" %
525 067dda99 Vangelis Koukis
                              (GANETI_RAPI_VERSION, instance)), query, None)
526 067dda99 Vangelis Koukis
527 067dda99 Vangelis Koukis
  def DeactivateInstanceDisks(self, instance):
528 067dda99 Vangelis Koukis
    """Deactivates an instance's disks.
529 067dda99 Vangelis Koukis

530 067dda99 Vangelis Koukis
    @type instance: string
531 067dda99 Vangelis Koukis
    @param instance: Instance name
532 a3ad611d Dimitris Aragiorgis
    @rtype: string
533 067dda99 Vangelis Koukis
    @return: job id
534 067dda99 Vangelis Koukis

535 067dda99 Vangelis Koukis
    """
536 067dda99 Vangelis Koukis
    return self._SendRequest(HTTP_PUT,
537 067dda99 Vangelis Koukis
                             ("/%s/instances/%s/deactivate-disks" %
538 067dda99 Vangelis Koukis
                              (GANETI_RAPI_VERSION, instance)), None, None)
539 067dda99 Vangelis Koukis
540 a3ad611d Dimitris Aragiorgis
  def RecreateInstanceDisks(self, instance, disks=None, nodes=None):
541 a3ad611d Dimitris Aragiorgis
    """Recreate an instance's disks.
542 a3ad611d Dimitris Aragiorgis

543 a3ad611d Dimitris Aragiorgis
    @type instance: string
544 a3ad611d Dimitris Aragiorgis
    @param instance: Instance name
545 a3ad611d Dimitris Aragiorgis
    @type disks: list of int
546 a3ad611d Dimitris Aragiorgis
    @param disks: List of disk indexes
547 a3ad611d Dimitris Aragiorgis
    @type nodes: list of string
548 a3ad611d Dimitris Aragiorgis
    @param nodes: New instance nodes, if relocation is desired
549 a3ad611d Dimitris Aragiorgis
    @rtype: string
550 a3ad611d Dimitris Aragiorgis
    @return: job id
551 a3ad611d Dimitris Aragiorgis

552 a3ad611d Dimitris Aragiorgis
    """
553 a3ad611d Dimitris Aragiorgis
    body = {}
554 a3ad611d Dimitris Aragiorgis
    _SetItemIf(body, disks is not None, "disks", disks)
555 a3ad611d Dimitris Aragiorgis
    _SetItemIf(body, nodes is not None, "nodes", nodes)
556 a3ad611d Dimitris Aragiorgis
557 a3ad611d Dimitris Aragiorgis
    return self._SendRequest(HTTP_POST,
558 a3ad611d Dimitris Aragiorgis
                             ("/%s/instances/%s/recreate-disks" %
559 a3ad611d Dimitris Aragiorgis
                              (GANETI_RAPI_VERSION, instance)), None, body)
560 a3ad611d Dimitris Aragiorgis
561 067dda99 Vangelis Koukis
  def GrowInstanceDisk(self, instance, disk, amount, wait_for_sync=None):
562 067dda99 Vangelis Koukis
    """Grows a disk of an instance.
563 067dda99 Vangelis Koukis

564 067dda99 Vangelis Koukis
    More details for parameters can be found in the RAPI documentation.
565 067dda99 Vangelis Koukis

566 067dda99 Vangelis Koukis
    @type instance: string
567 067dda99 Vangelis Koukis
    @param instance: Instance name
568 067dda99 Vangelis Koukis
    @type disk: integer
569 067dda99 Vangelis Koukis
    @param disk: Disk index
570 067dda99 Vangelis Koukis
    @type amount: integer
571 067dda99 Vangelis Koukis
    @param amount: Grow disk by this amount (MiB)
572 067dda99 Vangelis Koukis
    @type wait_for_sync: bool
573 067dda99 Vangelis Koukis
    @param wait_for_sync: Wait for disk to synchronize
574 a3ad611d Dimitris Aragiorgis
    @rtype: string
575 067dda99 Vangelis Koukis
    @return: job id
576 067dda99 Vangelis Koukis

577 067dda99 Vangelis Koukis
    """
578 067dda99 Vangelis Koukis
    body = {
579 067dda99 Vangelis Koukis
      "amount": amount,
580 067dda99 Vangelis Koukis
      }
581 067dda99 Vangelis Koukis
582 a3ad611d Dimitris Aragiorgis
    _SetItemIf(body, wait_for_sync is not None, "wait_for_sync", wait_for_sync)
583 067dda99 Vangelis Koukis
584 067dda99 Vangelis Koukis
    return self._SendRequest(HTTP_POST,
585 067dda99 Vangelis Koukis
                             ("/%s/instances/%s/disk/%s/grow" %
586 067dda99 Vangelis Koukis
                              (GANETI_RAPI_VERSION, instance, disk)),
587 067dda99 Vangelis Koukis
                             None, body)
588 067dda99 Vangelis Koukis
589 e5e20779 Faidon Liambotis
  def GetInstanceTags(self, instance):
590 e5e20779 Faidon Liambotis
    """Gets tags for an instance.
591 e5e20779 Faidon Liambotis

592 e5e20779 Faidon Liambotis
    @type instance: str
593 e5e20779 Faidon Liambotis
    @param instance: instance whose tags to return
594 e5e20779 Faidon Liambotis

595 e5e20779 Faidon Liambotis
    @rtype: list of str
596 e5e20779 Faidon Liambotis
    @return: tags for the instance
597 e5e20779 Faidon Liambotis

598 e5e20779 Faidon Liambotis
    """
599 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_GET,
600 e5e20779 Faidon Liambotis
                             ("/%s/instances/%s/tags" %
601 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, instance)), None, None)
602 e5e20779 Faidon Liambotis
603 e5e20779 Faidon Liambotis
  def AddInstanceTags(self, instance, tags, dry_run=False):
604 e5e20779 Faidon Liambotis
    """Adds tags to an instance.
605 e5e20779 Faidon Liambotis

606 e5e20779 Faidon Liambotis
    @type instance: str
607 e5e20779 Faidon Liambotis
    @param instance: instance to add tags to
608 e5e20779 Faidon Liambotis
    @type tags: list of str
609 e5e20779 Faidon Liambotis
    @param tags: tags to add to the instance
610 e5e20779 Faidon Liambotis
    @type dry_run: bool
611 e5e20779 Faidon Liambotis
    @param dry_run: whether to perform a dry run
612 e5e20779 Faidon Liambotis

613 a3ad611d Dimitris Aragiorgis
    @rtype: string
614 e5e20779 Faidon Liambotis
    @return: job id
615 e5e20779 Faidon Liambotis

616 e5e20779 Faidon Liambotis
    """
617 e5e20779 Faidon Liambotis
    query = [("tag", t) for t in tags]
618 a3ad611d Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
619 e5e20779 Faidon Liambotis
620 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_PUT,
621 e5e20779 Faidon Liambotis
                             ("/%s/instances/%s/tags" %
622 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, instance)), query, None)
623 e5e20779 Faidon Liambotis
624 e5e20779 Faidon Liambotis
  def DeleteInstanceTags(self, instance, tags, dry_run=False):
625 e5e20779 Faidon Liambotis
    """Deletes tags from an instance.
626 e5e20779 Faidon Liambotis

627 e5e20779 Faidon Liambotis
    @type instance: str
628 e5e20779 Faidon Liambotis
    @param instance: instance to delete tags from
629 e5e20779 Faidon Liambotis
    @type tags: list of str
630 e5e20779 Faidon Liambotis
    @param tags: tags to delete
631 e5e20779 Faidon Liambotis
    @type dry_run: bool
632 e5e20779 Faidon Liambotis
    @param dry_run: whether to perform a dry run
633 a3ad611d Dimitris Aragiorgis
    @rtype: string
634 a3ad611d Dimitris Aragiorgis
    @return: job id
635 e5e20779 Faidon Liambotis

636 e5e20779 Faidon Liambotis
    """
637 e5e20779 Faidon Liambotis
    query = [("tag", t) for t in tags]
638 a3ad611d Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
639 e5e20779 Faidon Liambotis
640 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_DELETE,
641 e5e20779 Faidon Liambotis
                             ("/%s/instances/%s/tags" %
642 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, instance)), query, None)
643 e5e20779 Faidon Liambotis
644 e5e20779 Faidon Liambotis
  def RebootInstance(self, instance, reboot_type=None, ignore_secondaries=None,
645 e5e20779 Faidon Liambotis
                     dry_run=False):
646 e5e20779 Faidon Liambotis
    """Reboots an instance.
647 e5e20779 Faidon Liambotis

648 e5e20779 Faidon Liambotis
    @type instance: str
649 e5e20779 Faidon Liambotis
    @param instance: instance to rebot
650 e5e20779 Faidon Liambotis
    @type reboot_type: str
651 e5e20779 Faidon Liambotis
    @param reboot_type: one of: hard, soft, full
652 e5e20779 Faidon Liambotis
    @type ignore_secondaries: bool
653 e5e20779 Faidon Liambotis
    @param ignore_secondaries: if True, ignores errors for the secondary node
654 e5e20779 Faidon Liambotis
        while re-assembling disks (in hard-reboot mode only)
655 e5e20779 Faidon Liambotis
    @type dry_run: bool
656 e5e20779 Faidon Liambotis
    @param dry_run: whether to perform a dry run
657 a3ad611d Dimitris Aragiorgis
    @rtype: string
658 a3ad611d Dimitris Aragiorgis
    @return: job id
659 e5e20779 Faidon Liambotis

660 e5e20779 Faidon Liambotis
    """
661 e5e20779 Faidon Liambotis
    query = []
662 a3ad611d Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
663 a3ad611d Dimitris Aragiorgis
    _AppendIf(query, reboot_type, ("type", reboot_type))
664 a3ad611d Dimitris Aragiorgis
    _AppendIf(query, ignore_secondaries is not None,
665 a3ad611d Dimitris Aragiorgis
              ("ignore_secondaries", ignore_secondaries))
666 e5e20779 Faidon Liambotis
667 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_POST,
668 e5e20779 Faidon Liambotis
                             ("/%s/instances/%s/reboot" %
669 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, instance)), query, None)
670 e5e20779 Faidon Liambotis
671 a3ad611d Dimitris Aragiorgis
  def ShutdownInstance(self, instance, dry_run=False, no_remember=False):
672 e5e20779 Faidon Liambotis
    """Shuts down an instance.
673 e5e20779 Faidon Liambotis

674 e5e20779 Faidon Liambotis
    @type instance: str
675 e5e20779 Faidon Liambotis
    @param instance: the instance to shut down
676 e5e20779 Faidon Liambotis
    @type dry_run: bool
677 e5e20779 Faidon Liambotis
    @param dry_run: whether to perform a dry run
678 a3ad611d Dimitris Aragiorgis
    @type no_remember: bool
679 a3ad611d Dimitris Aragiorgis
    @param no_remember: if true, will not record the state change
680 a3ad611d Dimitris Aragiorgis
    @rtype: string
681 a3ad611d Dimitris Aragiorgis
    @return: job id
682 e5e20779 Faidon Liambotis

683 e5e20779 Faidon Liambotis
    """
684 e5e20779 Faidon Liambotis
    query = []
685 a3ad611d Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
686 a3ad611d Dimitris Aragiorgis
    _AppendIf(query, no_remember, ("no-remember", 1))
687 e5e20779 Faidon Liambotis
688 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_PUT,
689 e5e20779 Faidon Liambotis
                             ("/%s/instances/%s/shutdown" %
690 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, instance)), query, None)
691 e5e20779 Faidon Liambotis
692 a3ad611d Dimitris Aragiorgis
  def StartupInstance(self, instance, dry_run=False, no_remember=False):
693 e5e20779 Faidon Liambotis
    """Starts up an instance.
694 e5e20779 Faidon Liambotis

695 e5e20779 Faidon Liambotis
    @type instance: str
696 e5e20779 Faidon Liambotis
    @param instance: the instance to start up
697 e5e20779 Faidon Liambotis
    @type dry_run: bool
698 e5e20779 Faidon Liambotis
    @param dry_run: whether to perform a dry run
699 a3ad611d Dimitris Aragiorgis
    @type no_remember: bool
700 a3ad611d Dimitris Aragiorgis
    @param no_remember: if true, will not record the state change
701 a3ad611d Dimitris Aragiorgis
    @rtype: string
702 a3ad611d Dimitris Aragiorgis
    @return: job id
703 e5e20779 Faidon Liambotis

704 e5e20779 Faidon Liambotis
    """
705 e5e20779 Faidon Liambotis
    query = []
706 a3ad611d Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
707 a3ad611d Dimitris Aragiorgis
    _AppendIf(query, no_remember, ("no-remember", 1))
708 e5e20779 Faidon Liambotis
709 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_PUT,
710 e5e20779 Faidon Liambotis
                             ("/%s/instances/%s/startup" %
711 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, instance)), query, None)
712 e5e20779 Faidon Liambotis
713 067dda99 Vangelis Koukis
  def ReinstallInstance(self, instance, os=None, no_startup=False,
714 067dda99 Vangelis Koukis
                        osparams=None):
715 e5e20779 Faidon Liambotis
    """Reinstalls an instance.
716 e5e20779 Faidon Liambotis

717 e5e20779 Faidon Liambotis
    @type instance: str
718 e5e20779 Faidon Liambotis
    @param instance: The instance to reinstall
719 e5e20779 Faidon Liambotis
    @type os: str or None
720 e5e20779 Faidon Liambotis
    @param os: The operating system to reinstall. If None, the instance's
721 e5e20779 Faidon Liambotis
        current operating system will be installed again
722 e5e20779 Faidon Liambotis
    @type no_startup: bool
723 e5e20779 Faidon Liambotis
    @param no_startup: Whether to start the instance automatically
724 a3ad611d Dimitris Aragiorgis
    @rtype: string
725 a3ad611d Dimitris Aragiorgis
    @return: job id
726 e5e20779 Faidon Liambotis

727 e5e20779 Faidon Liambotis
    """
728 067dda99 Vangelis Koukis
    if _INST_REINSTALL_REQV1 in self.GetFeatures():
729 067dda99 Vangelis Koukis
      body = {
730 067dda99 Vangelis Koukis
        "start": not no_startup,
731 067dda99 Vangelis Koukis
        }
732 a3ad611d Dimitris Aragiorgis
      _SetItemIf(body, os is not None, "os", os)
733 a3ad611d Dimitris Aragiorgis
      _SetItemIf(body, osparams is not None, "osparams", osparams)
734 067dda99 Vangelis Koukis
      return self._SendRequest(HTTP_POST,
735 067dda99 Vangelis Koukis
                               ("/%s/instances/%s/reinstall" %
736 067dda99 Vangelis Koukis
                                (GANETI_RAPI_VERSION, instance)), None, body)
737 067dda99 Vangelis Koukis
738 067dda99 Vangelis Koukis
    # Use old request format
739 067dda99 Vangelis Koukis
    if osparams:
740 067dda99 Vangelis Koukis
      raise GanetiApiError("Server does not support specifying OS parameters"
741 067dda99 Vangelis Koukis
                           " for instance reinstallation")
742 067dda99 Vangelis Koukis
743 e5e20779 Faidon Liambotis
    query = []
744 a3ad611d Dimitris Aragiorgis
    _AppendIf(query, os, ("os", os))
745 a3ad611d Dimitris Aragiorgis
    _AppendIf(query, no_startup, ("nostartup", 1))
746 a3ad611d Dimitris Aragiorgis
747 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_POST,
748 e5e20779 Faidon Liambotis
                             ("/%s/instances/%s/reinstall" %
749 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, instance)), query, None)
750 e5e20779 Faidon Liambotis
751 e5e20779 Faidon Liambotis
  def ReplaceInstanceDisks(self, instance, disks=None, mode=REPLACE_DISK_AUTO,
752 a3ad611d Dimitris Aragiorgis
                           remote_node=None, iallocator=None):
753 e5e20779 Faidon Liambotis
    """Replaces disks on an instance.
754 e5e20779 Faidon Liambotis

755 e5e20779 Faidon Liambotis
    @type instance: str
756 e5e20779 Faidon Liambotis
    @param instance: instance whose disks to replace
757 e5e20779 Faidon Liambotis
    @type disks: list of ints
758 e5e20779 Faidon Liambotis
    @param disks: Indexes of disks to replace
759 e5e20779 Faidon Liambotis
    @type mode: str
760 e5e20779 Faidon Liambotis
    @param mode: replacement mode to use (defaults to replace_auto)
761 e5e20779 Faidon Liambotis
    @type remote_node: str or None
762 e5e20779 Faidon Liambotis
    @param remote_node: new secondary node to use (for use with
763 e5e20779 Faidon Liambotis
        replace_new_secondary mode)
764 e5e20779 Faidon Liambotis
    @type iallocator: str or None
765 e5e20779 Faidon Liambotis
    @param iallocator: instance allocator plugin to use (for use with
766 e5e20779 Faidon Liambotis
                       replace_auto mode)
767 e5e20779 Faidon Liambotis

768 a3ad611d Dimitris Aragiorgis
    @rtype: string
769 e5e20779 Faidon Liambotis
    @return: job id
770 e5e20779 Faidon Liambotis

771 e5e20779 Faidon Liambotis
    """
772 e5e20779 Faidon Liambotis
    query = [
773 e5e20779 Faidon Liambotis
      ("mode", mode),
774 e5e20779 Faidon Liambotis
      ]
775 e5e20779 Faidon Liambotis
776 a3ad611d Dimitris Aragiorgis
    # TODO: Convert to body parameters
777 e5e20779 Faidon Liambotis
778 a3ad611d Dimitris Aragiorgis
    if disks is not None:
779 a3ad611d Dimitris Aragiorgis
      _AppendIf(query, True,
780 a3ad611d Dimitris Aragiorgis
                ("disks", ",".join(str(idx) for idx in disks)))
781 e5e20779 Faidon Liambotis
782 a3ad611d Dimitris Aragiorgis
    _AppendIf(query, remote_node is not None, ("remote_node", remote_node))
783 a3ad611d Dimitris Aragiorgis
    _AppendIf(query, iallocator is not None, ("iallocator", iallocator))
784 e5e20779 Faidon Liambotis
785 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_POST,
786 e5e20779 Faidon Liambotis
                             ("/%s/instances/%s/replace-disks" %
787 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, instance)), query, None)
788 e5e20779 Faidon Liambotis
789 e5e20779 Faidon Liambotis
  def PrepareExport(self, instance, mode):
790 e5e20779 Faidon Liambotis
    """Prepares an instance for an export.
791 e5e20779 Faidon Liambotis

792 e5e20779 Faidon Liambotis
    @type instance: string
793 e5e20779 Faidon Liambotis
    @param instance: Instance name
794 e5e20779 Faidon Liambotis
    @type mode: string
795 e5e20779 Faidon Liambotis
    @param mode: Export mode
796 e5e20779 Faidon Liambotis
    @rtype: string
797 e5e20779 Faidon Liambotis
    @return: Job ID
798 e5e20779 Faidon Liambotis

799 e5e20779 Faidon Liambotis
    """
800 e5e20779 Faidon Liambotis
    query = [("mode", mode)]
801 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_PUT,
802 e5e20779 Faidon Liambotis
                             ("/%s/instances/%s/prepare-export" %
803 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, instance)), query, None)
804 e5e20779 Faidon Liambotis
805 e5e20779 Faidon Liambotis
  def ExportInstance(self, instance, mode, destination, shutdown=None,
806 e5e20779 Faidon Liambotis
                     remove_instance=None,
807 e5e20779 Faidon Liambotis
                     x509_key_name=None, destination_x509_ca=None):
808 e5e20779 Faidon Liambotis
    """Exports an instance.
809 e5e20779 Faidon Liambotis

810 e5e20779 Faidon Liambotis
    @type instance: string
811 e5e20779 Faidon Liambotis
    @param instance: Instance name
812 e5e20779 Faidon Liambotis
    @type mode: string
813 e5e20779 Faidon Liambotis
    @param mode: Export mode
814 e5e20779 Faidon Liambotis
    @rtype: string
815 e5e20779 Faidon Liambotis
    @return: Job ID
816 e5e20779 Faidon Liambotis

817 e5e20779 Faidon Liambotis
    """
818 e5e20779 Faidon Liambotis
    body = {
819 e5e20779 Faidon Liambotis
      "destination": destination,
820 e5e20779 Faidon Liambotis
      "mode": mode,
821 e5e20779 Faidon Liambotis
      }
822 e5e20779 Faidon Liambotis
823 a3ad611d Dimitris Aragiorgis
    _SetItemIf(body, shutdown is not None, "shutdown", shutdown)
824 a3ad611d Dimitris Aragiorgis
    _SetItemIf(body, remove_instance is not None,
825 a3ad611d Dimitris Aragiorgis
               "remove_instance", remove_instance)
826 a3ad611d Dimitris Aragiorgis
    _SetItemIf(body, x509_key_name is not None, "x509_key_name", x509_key_name)
827 a3ad611d Dimitris Aragiorgis
    _SetItemIf(body, destination_x509_ca is not None,
828 a3ad611d Dimitris Aragiorgis
               "destination_x509_ca", destination_x509_ca)
829 e5e20779 Faidon Liambotis
830 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_PUT,
831 e5e20779 Faidon Liambotis
                             ("/%s/instances/%s/export" %
832 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, instance)), None, body)
833 e5e20779 Faidon Liambotis
834 e5e20779 Faidon Liambotis
  def MigrateInstance(self, instance, mode=None, cleanup=None):
835 e5e20779 Faidon Liambotis
    """Migrates an instance.
836 e5e20779 Faidon Liambotis

837 e5e20779 Faidon Liambotis
    @type instance: string
838 e5e20779 Faidon Liambotis
    @param instance: Instance name
839 e5e20779 Faidon Liambotis
    @type mode: string
840 e5e20779 Faidon Liambotis
    @param mode: Migration mode
841 e5e20779 Faidon Liambotis
    @type cleanup: bool
842 e5e20779 Faidon Liambotis
    @param cleanup: Whether to clean up a previously failed migration
843 a3ad611d Dimitris Aragiorgis
    @rtype: string
844 a3ad611d Dimitris Aragiorgis
    @return: job id
845 e5e20779 Faidon Liambotis

846 e5e20779 Faidon Liambotis
    """
847 e5e20779 Faidon Liambotis
    body = {}
848 a3ad611d Dimitris Aragiorgis
    _SetItemIf(body, mode is not None, "mode", mode)
849 a3ad611d Dimitris Aragiorgis
    _SetItemIf(body, cleanup is not None, "cleanup", cleanup)
850 e5e20779 Faidon Liambotis
851 a3ad611d Dimitris Aragiorgis
    return self._SendRequest(HTTP_PUT,
852 a3ad611d Dimitris Aragiorgis
                             ("/%s/instances/%s/migrate" %
853 a3ad611d Dimitris Aragiorgis
                              (GANETI_RAPI_VERSION, instance)), None, body)
854 e5e20779 Faidon Liambotis
855 a3ad611d Dimitris Aragiorgis
  def FailoverInstance(self, instance, iallocator=None,
856 a3ad611d Dimitris Aragiorgis
                       ignore_consistency=None, target_node=None):
857 a3ad611d Dimitris Aragiorgis
    """Does a failover of an instance.
858 a3ad611d Dimitris Aragiorgis

859 a3ad611d Dimitris Aragiorgis
    @type instance: string
860 a3ad611d Dimitris Aragiorgis
    @param instance: Instance name
861 a3ad611d Dimitris Aragiorgis
    @type iallocator: string
862 a3ad611d Dimitris Aragiorgis
    @param iallocator: Iallocator for deciding the target node for
863 a3ad611d Dimitris Aragiorgis
      shared-storage instances
864 a3ad611d Dimitris Aragiorgis
    @type ignore_consistency: bool
865 a3ad611d Dimitris Aragiorgis
    @param ignore_consistency: Whether to ignore disk consistency
866 a3ad611d Dimitris Aragiorgis
    @type target_node: string
867 a3ad611d Dimitris Aragiorgis
    @param target_node: Target node for shared-storage instances
868 a3ad611d Dimitris Aragiorgis
    @rtype: string
869 a3ad611d Dimitris Aragiorgis
    @return: job id
870 a3ad611d Dimitris Aragiorgis

871 a3ad611d Dimitris Aragiorgis
    """
872 a3ad611d Dimitris Aragiorgis
    body = {}
873 a3ad611d Dimitris Aragiorgis
    _SetItemIf(body, iallocator is not None, "iallocator", iallocator)
874 a3ad611d Dimitris Aragiorgis
    _SetItemIf(body, ignore_consistency is not None,
875 a3ad611d Dimitris Aragiorgis
               "ignore_consistency", ignore_consistency)
876 a3ad611d Dimitris Aragiorgis
    _SetItemIf(body, target_node is not None, "target_node", target_node)
877 e5e20779 Faidon Liambotis
878 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_PUT,
879 a3ad611d Dimitris Aragiorgis
                             ("/%s/instances/%s/failover" %
880 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, instance)), None, body)
881 e5e20779 Faidon Liambotis
882 e5e20779 Faidon Liambotis
  def RenameInstance(self, instance, new_name, ip_check=None, name_check=None):
883 e5e20779 Faidon Liambotis
    """Changes the name of an instance.
884 e5e20779 Faidon Liambotis

885 e5e20779 Faidon Liambotis
    @type instance: string
886 e5e20779 Faidon Liambotis
    @param instance: Instance name
887 e5e20779 Faidon Liambotis
    @type new_name: string
888 e5e20779 Faidon Liambotis
    @param new_name: New instance name
889 e5e20779 Faidon Liambotis
    @type ip_check: bool
890 e5e20779 Faidon Liambotis
    @param ip_check: Whether to ensure instance's IP address is inactive
891 e5e20779 Faidon Liambotis
    @type name_check: bool
892 e5e20779 Faidon Liambotis
    @param name_check: Whether to ensure instance's name is resolvable
893 a3ad611d Dimitris Aragiorgis
    @rtype: string
894 a3ad611d Dimitris Aragiorgis
    @return: job id
895 e5e20779 Faidon Liambotis

896 e5e20779 Faidon Liambotis
    """
897 e5e20779 Faidon Liambotis
    body = {
898 e5e20779 Faidon Liambotis
      "new_name": new_name,
899 e5e20779 Faidon Liambotis
      }
900 e5e20779 Faidon Liambotis
901 a3ad611d Dimitris Aragiorgis
    _SetItemIf(body, ip_check is not None, "ip_check", ip_check)
902 a3ad611d Dimitris Aragiorgis
    _SetItemIf(body, name_check is not None, "name_check", name_check)
903 e5e20779 Faidon Liambotis
904 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_PUT,
905 e5e20779 Faidon Liambotis
                             ("/%s/instances/%s/rename" %
906 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, instance)), None, body)
907 e5e20779 Faidon Liambotis
908 067dda99 Vangelis Koukis
  def GetInstanceConsole(self, instance):
909 067dda99 Vangelis Koukis
    """Request information for connecting to instance's console.
910 067dda99 Vangelis Koukis

911 067dda99 Vangelis Koukis
    @type instance: string
912 067dda99 Vangelis Koukis
    @param instance: Instance name
913 a3ad611d Dimitris Aragiorgis
    @rtype: dict
914 a3ad611d Dimitris Aragiorgis
    @return: dictionary containing information about instance's console
915 067dda99 Vangelis Koukis

916 067dda99 Vangelis Koukis
    """
917 067dda99 Vangelis Koukis
    return self._SendRequest(HTTP_GET,
918 067dda99 Vangelis Koukis
                             ("/%s/instances/%s/console" %
919 067dda99 Vangelis Koukis
                              (GANETI_RAPI_VERSION, instance)), None, None)
920 067dda99 Vangelis Koukis
921 70a0afab Christos Stavrakakis
  def GetJobs(self, bulk=False):
922 e5e20779 Faidon Liambotis
    """Gets all jobs for the cluster.
923 e5e20779 Faidon Liambotis

924 e5e20779 Faidon Liambotis
    @rtype: list of int
925 e5e20779 Faidon Liambotis
    @return: job ids for the cluster
926 e5e20779 Faidon Liambotis

927 e5e20779 Faidon Liambotis
    """
928 70a0afab Christos Stavrakakis
    query = []
929 70a0afab Christos Stavrakakis
    _AppendIf(query, bulk, ("bulk", 1))
930 70a0afab Christos Stavrakakis
931 70a0afab Christos Stavrakakis
    jobs = self._SendRequest(HTTP_GET, "/%s/jobs" % GANETI_RAPI_VERSION,
932 70a0afab Christos Stavrakakis
                             query, None)
933 70a0afab Christos Stavrakakis
    if bulk:
934 70a0afab Christos Stavrakakis
        return jobs
935 70a0afab Christos Stavrakakis
    else:
936 70a0afab Christos Stavrakakis
        return [int(j["id"]) for j in jobs]
937 70a0afab Christos Stavrakakis
938 e5e20779 Faidon Liambotis
939 e5e20779 Faidon Liambotis
  def GetJobStatus(self, job_id):
940 e5e20779 Faidon Liambotis
    """Gets the status of a job.
941 e5e20779 Faidon Liambotis

942 a3ad611d Dimitris Aragiorgis
    @type job_id: string
943 e5e20779 Faidon Liambotis
    @param job_id: job id whose status to query
944 e5e20779 Faidon Liambotis

945 e5e20779 Faidon Liambotis
    @rtype: dict
946 e5e20779 Faidon Liambotis
    @return: job status
947 e5e20779 Faidon Liambotis

948 e5e20779 Faidon Liambotis
    """
949 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_GET,
950 e5e20779 Faidon Liambotis
                             "/%s/jobs/%s" % (GANETI_RAPI_VERSION, job_id),
951 e5e20779 Faidon Liambotis
                             None, None)
952 e5e20779 Faidon Liambotis
953 a3ad611d Dimitris Aragiorgis
  def WaitForJobCompletion(self, job_id, period=5, retries=-1):
954 a3ad611d Dimitris Aragiorgis
    """Polls cluster for job status until completion.
955 a3ad611d Dimitris Aragiorgis

956 a3ad611d Dimitris Aragiorgis
    Completion is defined as any of the following states listed in
957 a3ad611d Dimitris Aragiorgis
    L{JOB_STATUS_FINALIZED}.
958 a3ad611d Dimitris Aragiorgis

959 a3ad611d Dimitris Aragiorgis
    @type job_id: string
960 a3ad611d Dimitris Aragiorgis
    @param job_id: job id to watch
961 a3ad611d Dimitris Aragiorgis
    @type period: int
962 a3ad611d Dimitris Aragiorgis
    @param period: how often to poll for status (optional, default 5s)
963 a3ad611d Dimitris Aragiorgis
    @type retries: int
964 a3ad611d Dimitris Aragiorgis
    @param retries: how many time to poll before giving up
965 a3ad611d Dimitris Aragiorgis
                    (optional, default -1 means unlimited)
966 a3ad611d Dimitris Aragiorgis

967 a3ad611d Dimitris Aragiorgis
    @rtype: bool
968 a3ad611d Dimitris Aragiorgis
    @return: C{True} if job succeeded or C{False} if failed/status timeout
969 a3ad611d Dimitris Aragiorgis
    @deprecated: It is recommended to use L{WaitForJobChange} wherever
970 a3ad611d Dimitris Aragiorgis
      possible; L{WaitForJobChange} returns immediately after a job changed and
971 a3ad611d Dimitris Aragiorgis
      does not use polling
972 a3ad611d Dimitris Aragiorgis

973 a3ad611d Dimitris Aragiorgis
    """
974 a3ad611d Dimitris Aragiorgis
    while retries != 0:
975 a3ad611d Dimitris Aragiorgis
      job_result = self.GetJobStatus(job_id)
976 a3ad611d Dimitris Aragiorgis
977 a3ad611d Dimitris Aragiorgis
      if job_result and job_result["status"] == JOB_STATUS_SUCCESS:
978 a3ad611d Dimitris Aragiorgis
        return True
979 a3ad611d Dimitris Aragiorgis
      elif not job_result or job_result["status"] in JOB_STATUS_FINALIZED:
980 a3ad611d Dimitris Aragiorgis
        return False
981 a3ad611d Dimitris Aragiorgis
982 a3ad611d Dimitris Aragiorgis
      if period:
983 a3ad611d Dimitris Aragiorgis
        time.sleep(period)
984 a3ad611d Dimitris Aragiorgis
985 a3ad611d Dimitris Aragiorgis
      if retries > 0:
986 a3ad611d Dimitris Aragiorgis
        retries -= 1
987 a3ad611d Dimitris Aragiorgis
988 a3ad611d Dimitris Aragiorgis
    return False
989 a3ad611d Dimitris Aragiorgis
990 e5e20779 Faidon Liambotis
  def WaitForJobChange(self, job_id, fields, prev_job_info, prev_log_serial):
991 e5e20779 Faidon Liambotis
    """Waits for job changes.
992 e5e20779 Faidon Liambotis

993 a3ad611d Dimitris Aragiorgis
    @type job_id: string
994 e5e20779 Faidon Liambotis
    @param job_id: Job ID for which to wait
995 a3ad611d Dimitris Aragiorgis
    @return: C{None} if no changes have been detected and a dict with two keys,
996 a3ad611d Dimitris Aragiorgis
      C{job_info} and C{log_entries} otherwise.
997 a3ad611d Dimitris Aragiorgis
    @rtype: dict
998 e5e20779 Faidon Liambotis

999 e5e20779 Faidon Liambotis
    """
1000 e5e20779 Faidon Liambotis
    body = {
1001 e5e20779 Faidon Liambotis
      "fields": fields,
1002 e5e20779 Faidon Liambotis
      "previous_job_info": prev_job_info,
1003 e5e20779 Faidon Liambotis
      "previous_log_serial": prev_log_serial,
1004 e5e20779 Faidon Liambotis
      }
1005 e5e20779 Faidon Liambotis
1006 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_GET,
1007 e5e20779 Faidon Liambotis
                             "/%s/jobs/%s/wait" % (GANETI_RAPI_VERSION, job_id),
1008 e5e20779 Faidon Liambotis
                             None, body)
1009 e5e20779 Faidon Liambotis
1010 e5e20779 Faidon Liambotis
  def CancelJob(self, job_id, dry_run=False):
1011 e5e20779 Faidon Liambotis
    """Cancels a job.
1012 e5e20779 Faidon Liambotis

1013 a3ad611d Dimitris Aragiorgis
    @type job_id: string
1014 e5e20779 Faidon Liambotis
    @param job_id: id of the job to delete
1015 e5e20779 Faidon Liambotis
    @type dry_run: bool
1016 e5e20779 Faidon Liambotis
    @param dry_run: whether to perform a dry run
1017 a3ad611d Dimitris Aragiorgis
    @rtype: tuple
1018 a3ad611d Dimitris Aragiorgis
    @return: tuple containing the result, and a message (bool, string)
1019 e5e20779 Faidon Liambotis

1020 e5e20779 Faidon Liambotis
    """
1021 e5e20779 Faidon Liambotis
    query = []
1022 a3ad611d Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
1023 e5e20779 Faidon Liambotis
1024 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_DELETE,
1025 e5e20779 Faidon Liambotis
                             "/%s/jobs/%s" % (GANETI_RAPI_VERSION, job_id),
1026 e5e20779 Faidon Liambotis
                             query, None)
1027 e5e20779 Faidon Liambotis
1028 e5e20779 Faidon Liambotis
  def GetNodes(self, bulk=False):
1029 e5e20779 Faidon Liambotis
    """Gets all nodes in the cluster.
1030 e5e20779 Faidon Liambotis

1031 e5e20779 Faidon Liambotis
    @type bulk: bool
1032 e5e20779 Faidon Liambotis
    @param bulk: whether to return all information about all instances
1033 e5e20779 Faidon Liambotis

1034 e5e20779 Faidon Liambotis
    @rtype: list of dict or str
1035 e5e20779 Faidon Liambotis
    @return: if bulk is true, info about nodes in the cluster,
1036 e5e20779 Faidon Liambotis
        else list of nodes in the cluster
1037 e5e20779 Faidon Liambotis

1038 e5e20779 Faidon Liambotis
    """
1039 e5e20779 Faidon Liambotis
    query = []
1040 a3ad611d Dimitris Aragiorgis
    _AppendIf(query, bulk, ("bulk", 1))
1041 e5e20779 Faidon Liambotis
1042 e5e20779 Faidon Liambotis
    nodes = self._SendRequest(HTTP_GET, "/%s/nodes" % GANETI_RAPI_VERSION,
1043 e5e20779 Faidon Liambotis
                              query, None)
1044 e5e20779 Faidon Liambotis
    if bulk:
1045 e5e20779 Faidon Liambotis
      return nodes
1046 e5e20779 Faidon Liambotis
    else:
1047 e5e20779 Faidon Liambotis
      return [n["id"] for n in nodes]
1048 e5e20779 Faidon Liambotis
1049 e5e20779 Faidon Liambotis
  def GetNode(self, node):
1050 e5e20779 Faidon Liambotis
    """Gets information about a node.
1051 e5e20779 Faidon Liambotis

1052 e5e20779 Faidon Liambotis
    @type node: str
1053 e5e20779 Faidon Liambotis
    @param node: node whose info to return
1054 e5e20779 Faidon Liambotis

1055 e5e20779 Faidon Liambotis
    @rtype: dict
1056 e5e20779 Faidon Liambotis
    @return: info about the node
1057 e5e20779 Faidon Liambotis

1058 e5e20779 Faidon Liambotis
    """
1059 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_GET,
1060 e5e20779 Faidon Liambotis
                             "/%s/nodes/%s" % (GANETI_RAPI_VERSION, node),
1061 e5e20779 Faidon Liambotis
                             None, None)
1062 e5e20779 Faidon Liambotis
1063 e5e20779 Faidon Liambotis
  def EvacuateNode(self, node, iallocator=None, remote_node=None,
1064 a3ad611d Dimitris Aragiorgis
                   dry_run=False, early_release=None,
1065 a3ad611d Dimitris Aragiorgis
                   mode=None, accept_old=False):
1066 e5e20779 Faidon Liambotis
    """Evacuates instances from a Ganeti node.
1067 e5e20779 Faidon Liambotis

1068 e5e20779 Faidon Liambotis
    @type node: str
1069 e5e20779 Faidon Liambotis
    @param node: node to evacuate
1070 e5e20779 Faidon Liambotis
    @type iallocator: str or None
1071 e5e20779 Faidon Liambotis
    @param iallocator: instance allocator to use
1072 e5e20779 Faidon Liambotis
    @type remote_node: str
1073 e5e20779 Faidon Liambotis
    @param remote_node: node to evaucate to
1074 e5e20779 Faidon Liambotis
    @type dry_run: bool
1075 e5e20779 Faidon Liambotis
    @param dry_run: whether to perform a dry run
1076 e5e20779 Faidon Liambotis
    @type early_release: bool
1077 e5e20779 Faidon Liambotis
    @param early_release: whether to enable parallelization
1078 a3ad611d Dimitris Aragiorgis
    @type mode: string
1079 a3ad611d Dimitris Aragiorgis
    @param mode: Node evacuation mode
1080 a3ad611d Dimitris Aragiorgis
    @type accept_old: bool
1081 a3ad611d Dimitris Aragiorgis
    @param accept_old: Whether caller is ready to accept old-style (pre-2.5)
1082 a3ad611d Dimitris Aragiorgis
        results
1083 e5e20779 Faidon Liambotis

1084 a3ad611d Dimitris Aragiorgis
    @rtype: string, or a list for pre-2.5 results
1085 a3ad611d Dimitris Aragiorgis
    @return: Job ID or, if C{accept_old} is set and server is pre-2.5,
1086 a3ad611d Dimitris Aragiorgis
      list of (job ID, instance name, new secondary node); if dry_run was
1087 a3ad611d Dimitris Aragiorgis
      specified, then the actual move jobs were not submitted and the job IDs
1088 a3ad611d Dimitris Aragiorgis
      will be C{None}
1089 e5e20779 Faidon Liambotis

1090 e5e20779 Faidon Liambotis
    @raises GanetiApiError: if an iallocator and remote_node are both
1091 e5e20779 Faidon Liambotis
        specified
1092 e5e20779 Faidon Liambotis

1093 e5e20779 Faidon Liambotis
    """
1094 e5e20779 Faidon Liambotis
    if iallocator and remote_node:
1095 e5e20779 Faidon Liambotis
      raise GanetiApiError("Only one of iallocator or remote_node can be used")
1096 e5e20779 Faidon Liambotis
1097 e5e20779 Faidon Liambotis
    query = []
1098 a3ad611d Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
1099 a3ad611d Dimitris Aragiorgis
1100 a3ad611d Dimitris Aragiorgis
    if _NODE_EVAC_RES1 in self.GetFeatures():
1101 a3ad611d Dimitris Aragiorgis
      # Server supports body parameters
1102 a3ad611d Dimitris Aragiorgis
      body = {}
1103 a3ad611d Dimitris Aragiorgis
1104 a3ad611d Dimitris Aragiorgis
      _SetItemIf(body, iallocator is not None, "iallocator", iallocator)
1105 a3ad611d Dimitris Aragiorgis
      _SetItemIf(body, remote_node is not None, "remote_node", remote_node)
1106 a3ad611d Dimitris Aragiorgis
      _SetItemIf(body, early_release is not None,
1107 a3ad611d Dimitris Aragiorgis
                 "early_release", early_release)
1108 a3ad611d Dimitris Aragiorgis
      _SetItemIf(body, mode is not None, "mode", mode)
1109 a3ad611d Dimitris Aragiorgis
    else:
1110 a3ad611d Dimitris Aragiorgis
      # Pre-2.5 request format
1111 a3ad611d Dimitris Aragiorgis
      body = None
1112 a3ad611d Dimitris Aragiorgis
1113 a3ad611d Dimitris Aragiorgis
      if not accept_old:
1114 a3ad611d Dimitris Aragiorgis
        raise GanetiApiError("Server is version 2.4 or earlier and caller does"
1115 a3ad611d Dimitris Aragiorgis
                             " not accept old-style results (parameter"
1116 a3ad611d Dimitris Aragiorgis
                             " accept_old)")
1117 a3ad611d Dimitris Aragiorgis
1118 a3ad611d Dimitris Aragiorgis
      # Pre-2.5 servers can only evacuate secondaries
1119 a3ad611d Dimitris Aragiorgis
      if mode is not None and mode != NODE_EVAC_SEC:
1120 a3ad611d Dimitris Aragiorgis
        raise GanetiApiError("Server can only evacuate secondary instances")
1121 a3ad611d Dimitris Aragiorgis
1122 a3ad611d Dimitris Aragiorgis
      _AppendIf(query, iallocator, ("iallocator", iallocator))
1123 a3ad611d Dimitris Aragiorgis
      _AppendIf(query, remote_node, ("remote_node", remote_node))
1124 a3ad611d Dimitris Aragiorgis
      _AppendIf(query, early_release, ("early_release", 1))
1125 e5e20779 Faidon Liambotis
1126 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_POST,
1127 e5e20779 Faidon Liambotis
                             ("/%s/nodes/%s/evacuate" %
1128 a3ad611d Dimitris Aragiorgis
                              (GANETI_RAPI_VERSION, node)), query, body)
1129 e5e20779 Faidon Liambotis
1130 a3ad611d Dimitris Aragiorgis
  def MigrateNode(self, node, mode=None, dry_run=False, iallocator=None,
1131 a3ad611d Dimitris Aragiorgis
                  target_node=None):
1132 e5e20779 Faidon Liambotis
    """Migrates all primary instances from a node.
1133 e5e20779 Faidon Liambotis

1134 e5e20779 Faidon Liambotis
    @type node: str
1135 e5e20779 Faidon Liambotis
    @param node: node to migrate
1136 e5e20779 Faidon Liambotis
    @type mode: string
1137 e5e20779 Faidon Liambotis
    @param mode: if passed, it will overwrite the live migration type,
1138 e5e20779 Faidon Liambotis
        otherwise the hypervisor default will be used
1139 e5e20779 Faidon Liambotis
    @type dry_run: bool
1140 e5e20779 Faidon Liambotis
    @param dry_run: whether to perform a dry run
1141 a3ad611d Dimitris Aragiorgis
    @type iallocator: string
1142 a3ad611d Dimitris Aragiorgis
    @param iallocator: instance allocator to use
1143 a3ad611d Dimitris Aragiorgis
    @type target_node: string
1144 a3ad611d Dimitris Aragiorgis
    @param target_node: Target node for shared-storage instances
1145 e5e20779 Faidon Liambotis

1146 a3ad611d Dimitris Aragiorgis
    @rtype: string
1147 e5e20779 Faidon Liambotis
    @return: job id
1148 e5e20779 Faidon Liambotis

1149 e5e20779 Faidon Liambotis
    """
1150 e5e20779 Faidon Liambotis
    query = []
1151 a3ad611d Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
1152 e5e20779 Faidon Liambotis
1153 a3ad611d Dimitris Aragiorgis
    if _NODE_MIGRATE_REQV1 in self.GetFeatures():
1154 a3ad611d Dimitris Aragiorgis
      body = {}
1155 a3ad611d Dimitris Aragiorgis
1156 a3ad611d Dimitris Aragiorgis
      _SetItemIf(body, mode is not None, "mode", mode)
1157 a3ad611d Dimitris Aragiorgis
      _SetItemIf(body, iallocator is not None, "iallocator", iallocator)
1158 a3ad611d Dimitris Aragiorgis
      _SetItemIf(body, target_node is not None, "target_node", target_node)
1159 a3ad611d Dimitris Aragiorgis
1160 a3ad611d Dimitris Aragiorgis
      assert len(query) <= 1
1161 a3ad611d Dimitris Aragiorgis
1162 a3ad611d Dimitris Aragiorgis
      return self._SendRequest(HTTP_POST,
1163 a3ad611d Dimitris Aragiorgis
                               ("/%s/nodes/%s/migrate" %
1164 a3ad611d Dimitris Aragiorgis
                                (GANETI_RAPI_VERSION, node)), query, body)
1165 a3ad611d Dimitris Aragiorgis
    else:
1166 a3ad611d Dimitris Aragiorgis
      # Use old request format
1167 a3ad611d Dimitris Aragiorgis
      if target_node is not None:
1168 a3ad611d Dimitris Aragiorgis
        raise GanetiApiError("Server does not support specifying target node"
1169 a3ad611d Dimitris Aragiorgis
                             " for node migration")
1170 a3ad611d Dimitris Aragiorgis
1171 a3ad611d Dimitris Aragiorgis
      _AppendIf(query, mode is not None, ("mode", mode))
1172 a3ad611d Dimitris Aragiorgis
1173 a3ad611d Dimitris Aragiorgis
      return self._SendRequest(HTTP_POST,
1174 a3ad611d Dimitris Aragiorgis
                               ("/%s/nodes/%s/migrate" %
1175 a3ad611d Dimitris Aragiorgis
                                (GANETI_RAPI_VERSION, node)), query, None)
1176 e5e20779 Faidon Liambotis
1177 e5e20779 Faidon Liambotis
  def GetNodeRole(self, node):
1178 e5e20779 Faidon Liambotis
    """Gets the current role for a node.
1179 e5e20779 Faidon Liambotis

1180 e5e20779 Faidon Liambotis
    @type node: str
1181 e5e20779 Faidon Liambotis
    @param node: node whose role to return
1182 e5e20779 Faidon Liambotis

1183 e5e20779 Faidon Liambotis
    @rtype: str
1184 e5e20779 Faidon Liambotis
    @return: the current role for a node
1185 e5e20779 Faidon Liambotis

1186 e5e20779 Faidon Liambotis
    """
1187 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_GET,
1188 e5e20779 Faidon Liambotis
                             ("/%s/nodes/%s/role" %
1189 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, node)), None, None)
1190 e5e20779 Faidon Liambotis
1191 a3ad611d Dimitris Aragiorgis
  def SetNodeRole(self, node, role, force=False, auto_promote=None):
1192 e5e20779 Faidon Liambotis
    """Sets the role for a node.
1193 e5e20779 Faidon Liambotis

1194 e5e20779 Faidon Liambotis
    @type node: str
1195 e5e20779 Faidon Liambotis
    @param node: the node whose role to set
1196 e5e20779 Faidon Liambotis
    @type role: str
1197 e5e20779 Faidon Liambotis
    @param role: the role to set for the node
1198 e5e20779 Faidon Liambotis
    @type force: bool
1199 e5e20779 Faidon Liambotis
    @param force: whether to force the role change
1200 a3ad611d Dimitris Aragiorgis
    @type auto_promote: bool
1201 a3ad611d Dimitris Aragiorgis
    @param auto_promote: Whether node(s) should be promoted to master candidate
1202 a3ad611d Dimitris Aragiorgis
                         if necessary
1203 e5e20779 Faidon Liambotis

1204 a3ad611d Dimitris Aragiorgis
    @rtype: string
1205 e5e20779 Faidon Liambotis
    @return: job id
1206 e5e20779 Faidon Liambotis

1207 e5e20779 Faidon Liambotis
    """
1208 a3ad611d Dimitris Aragiorgis
    query = []
1209 a3ad611d Dimitris Aragiorgis
    _AppendForceIf(query, force)
1210 a3ad611d Dimitris Aragiorgis
    _AppendIf(query, auto_promote is not None, ("auto-promote", auto_promote))
1211 e5e20779 Faidon Liambotis
1212 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_PUT,
1213 e5e20779 Faidon Liambotis
                             ("/%s/nodes/%s/role" %
1214 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, node)), query, role)
1215 e5e20779 Faidon Liambotis
1216 a3ad611d Dimitris Aragiorgis
  def PowercycleNode(self, node, force=False):
1217 a3ad611d Dimitris Aragiorgis
    """Powercycles a node.
1218 a3ad611d Dimitris Aragiorgis

1219 a3ad611d Dimitris Aragiorgis
    @type node: string
1220 a3ad611d Dimitris Aragiorgis
    @param node: Node name
1221 a3ad611d Dimitris Aragiorgis
    @type force: bool
1222 a3ad611d Dimitris Aragiorgis
    @param force: Whether to force the operation
1223 a3ad611d Dimitris Aragiorgis
    @rtype: string
1224 a3ad611d Dimitris Aragiorgis
    @return: job id
1225 a3ad611d Dimitris Aragiorgis

1226 a3ad611d Dimitris Aragiorgis
    """
1227 a3ad611d Dimitris Aragiorgis
    query = []
1228 a3ad611d Dimitris Aragiorgis
    _AppendForceIf(query, force)
1229 a3ad611d Dimitris Aragiorgis
1230 a3ad611d Dimitris Aragiorgis
    return self._SendRequest(HTTP_POST,
1231 a3ad611d Dimitris Aragiorgis
                             ("/%s/nodes/%s/powercycle" %
1232 a3ad611d Dimitris Aragiorgis
                              (GANETI_RAPI_VERSION, node)), query, None)
1233 a3ad611d Dimitris Aragiorgis
1234 a3ad611d Dimitris Aragiorgis
  def ModifyNode(self, node, **kwargs):
1235 a3ad611d Dimitris Aragiorgis
    """Modifies a node.
1236 a3ad611d Dimitris Aragiorgis

1237 a3ad611d Dimitris Aragiorgis
    More details for parameters can be found in the RAPI documentation.
1238 a3ad611d Dimitris Aragiorgis

1239 a3ad611d Dimitris Aragiorgis
    @type node: string
1240 a3ad611d Dimitris Aragiorgis
    @param node: Node name
1241 a3ad611d Dimitris Aragiorgis
    @rtype: string
1242 a3ad611d Dimitris Aragiorgis
    @return: job id
1243 a3ad611d Dimitris Aragiorgis

1244 a3ad611d Dimitris Aragiorgis
    """
1245 a3ad611d Dimitris Aragiorgis
    return self._SendRequest(HTTP_POST,
1246 a3ad611d Dimitris Aragiorgis
                             ("/%s/nodes/%s/modify" %
1247 a3ad611d Dimitris Aragiorgis
                              (GANETI_RAPI_VERSION, node)), None, kwargs)
1248 a3ad611d Dimitris Aragiorgis
1249 e5e20779 Faidon Liambotis
  def GetNodeStorageUnits(self, node, storage_type, output_fields):
1250 e5e20779 Faidon Liambotis
    """Gets the storage units for a node.
1251 e5e20779 Faidon Liambotis

1252 e5e20779 Faidon Liambotis
    @type node: str
1253 e5e20779 Faidon Liambotis
    @param node: the node whose storage units to return
1254 e5e20779 Faidon Liambotis
    @type storage_type: str
1255 e5e20779 Faidon Liambotis
    @param storage_type: storage type whose units to return
1256 e5e20779 Faidon Liambotis
    @type output_fields: str
1257 e5e20779 Faidon Liambotis
    @param output_fields: storage type fields to return
1258 e5e20779 Faidon Liambotis

1259 a3ad611d Dimitris Aragiorgis
    @rtype: string
1260 e5e20779 Faidon Liambotis
    @return: job id where results can be retrieved
1261 e5e20779 Faidon Liambotis

1262 e5e20779 Faidon Liambotis
    """
1263 e5e20779 Faidon Liambotis
    query = [
1264 e5e20779 Faidon Liambotis
      ("storage_type", storage_type),
1265 e5e20779 Faidon Liambotis
      ("output_fields", output_fields),
1266 e5e20779 Faidon Liambotis
      ]
1267 e5e20779 Faidon Liambotis
1268 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_GET,
1269 e5e20779 Faidon Liambotis
                             ("/%s/nodes/%s/storage" %
1270 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, node)), query, None)
1271 e5e20779 Faidon Liambotis
1272 e5e20779 Faidon Liambotis
  def ModifyNodeStorageUnits(self, node, storage_type, name, allocatable=None):
1273 e5e20779 Faidon Liambotis
    """Modifies parameters of storage units on the node.
1274 e5e20779 Faidon Liambotis

1275 e5e20779 Faidon Liambotis
    @type node: str
1276 e5e20779 Faidon Liambotis
    @param node: node whose storage units to modify
1277 e5e20779 Faidon Liambotis
    @type storage_type: str
1278 e5e20779 Faidon Liambotis
    @param storage_type: storage type whose units to modify
1279 e5e20779 Faidon Liambotis
    @type name: str
1280 e5e20779 Faidon Liambotis
    @param name: name of the storage unit
1281 e5e20779 Faidon Liambotis
    @type allocatable: bool or None
1282 e5e20779 Faidon Liambotis
    @param allocatable: Whether to set the "allocatable" flag on the storage
1283 e5e20779 Faidon Liambotis
                        unit (None=no modification, True=set, False=unset)
1284 e5e20779 Faidon Liambotis

1285 a3ad611d Dimitris Aragiorgis
    @rtype: string
1286 e5e20779 Faidon Liambotis
    @return: job id
1287 e5e20779 Faidon Liambotis

1288 e5e20779 Faidon Liambotis
    """
1289 e5e20779 Faidon Liambotis
    query = [
1290 e5e20779 Faidon Liambotis
      ("storage_type", storage_type),
1291 e5e20779 Faidon Liambotis
      ("name", name),
1292 e5e20779 Faidon Liambotis
      ]
1293 e5e20779 Faidon Liambotis
1294 a3ad611d Dimitris Aragiorgis
    _AppendIf(query, allocatable is not None, ("allocatable", allocatable))
1295 e5e20779 Faidon Liambotis
1296 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_PUT,
1297 e5e20779 Faidon Liambotis
                             ("/%s/nodes/%s/storage/modify" %
1298 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, node)), query, None)
1299 e5e20779 Faidon Liambotis
1300 e5e20779 Faidon Liambotis
  def RepairNodeStorageUnits(self, node, storage_type, name):
1301 e5e20779 Faidon Liambotis
    """Repairs a storage unit on the node.
1302 e5e20779 Faidon Liambotis

1303 e5e20779 Faidon Liambotis
    @type node: str
1304 e5e20779 Faidon Liambotis
    @param node: node whose storage units to repair
1305 e5e20779 Faidon Liambotis
    @type storage_type: str
1306 e5e20779 Faidon Liambotis
    @param storage_type: storage type to repair
1307 e5e20779 Faidon Liambotis
    @type name: str
1308 e5e20779 Faidon Liambotis
    @param name: name of the storage unit to repair
1309 e5e20779 Faidon Liambotis

1310 a3ad611d Dimitris Aragiorgis
    @rtype: string
1311 e5e20779 Faidon Liambotis
    @return: job id
1312 e5e20779 Faidon Liambotis

1313 e5e20779 Faidon Liambotis
    """
1314 e5e20779 Faidon Liambotis
    query = [
1315 e5e20779 Faidon Liambotis
      ("storage_type", storage_type),
1316 e5e20779 Faidon Liambotis
      ("name", name),
1317 e5e20779 Faidon Liambotis
      ]
1318 e5e20779 Faidon Liambotis
1319 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_PUT,
1320 e5e20779 Faidon Liambotis
                             ("/%s/nodes/%s/storage/repair" %
1321 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, node)), query, None)
1322 e5e20779 Faidon Liambotis
1323 e5e20779 Faidon Liambotis
  def GetNodeTags(self, node):
1324 e5e20779 Faidon Liambotis
    """Gets the tags for a node.
1325 e5e20779 Faidon Liambotis

1326 e5e20779 Faidon Liambotis
    @type node: str
1327 e5e20779 Faidon Liambotis
    @param node: node whose tags to return
1328 e5e20779 Faidon Liambotis

1329 e5e20779 Faidon Liambotis
    @rtype: list of str
1330 e5e20779 Faidon Liambotis
    @return: tags for the node
1331 e5e20779 Faidon Liambotis

1332 e5e20779 Faidon Liambotis
    """
1333 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_GET,
1334 e5e20779 Faidon Liambotis
                             ("/%s/nodes/%s/tags" %
1335 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, node)), None, None)
1336 e5e20779 Faidon Liambotis
1337 e5e20779 Faidon Liambotis
  def AddNodeTags(self, node, tags, dry_run=False):
1338 e5e20779 Faidon Liambotis
    """Adds tags to a node.
1339 e5e20779 Faidon Liambotis

1340 e5e20779 Faidon Liambotis
    @type node: str
1341 e5e20779 Faidon Liambotis
    @param node: node to add tags to
1342 e5e20779 Faidon Liambotis
    @type tags: list of str
1343 e5e20779 Faidon Liambotis
    @param tags: tags to add to the node
1344 e5e20779 Faidon Liambotis
    @type dry_run: bool
1345 e5e20779 Faidon Liambotis
    @param dry_run: whether to perform a dry run
1346 e5e20779 Faidon Liambotis

1347 a3ad611d Dimitris Aragiorgis
    @rtype: string
1348 e5e20779 Faidon Liambotis
    @return: job id
1349 e5e20779 Faidon Liambotis

1350 e5e20779 Faidon Liambotis
    """
1351 e5e20779 Faidon Liambotis
    query = [("tag", t) for t in tags]
1352 a3ad611d Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
1353 e5e20779 Faidon Liambotis
1354 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_PUT,
1355 e5e20779 Faidon Liambotis
                             ("/%s/nodes/%s/tags" %
1356 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, node)), query, tags)
1357 e5e20779 Faidon Liambotis
1358 e5e20779 Faidon Liambotis
  def DeleteNodeTags(self, node, tags, dry_run=False):
1359 e5e20779 Faidon Liambotis
    """Delete tags from a node.
1360 e5e20779 Faidon Liambotis

1361 e5e20779 Faidon Liambotis
    @type node: str
1362 e5e20779 Faidon Liambotis
    @param node: node to remove tags from
1363 e5e20779 Faidon Liambotis
    @type tags: list of str
1364 e5e20779 Faidon Liambotis
    @param tags: tags to remove from the node
1365 e5e20779 Faidon Liambotis
    @type dry_run: bool
1366 e5e20779 Faidon Liambotis
    @param dry_run: whether to perform a dry run
1367 e5e20779 Faidon Liambotis

1368 a3ad611d Dimitris Aragiorgis
    @rtype: string
1369 e5e20779 Faidon Liambotis
    @return: job id
1370 e5e20779 Faidon Liambotis

1371 e5e20779 Faidon Liambotis
    """
1372 e5e20779 Faidon Liambotis
    query = [("tag", t) for t in tags]
1373 a3ad611d Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
1374 e5e20779 Faidon Liambotis
1375 e5e20779 Faidon Liambotis
    return self._SendRequest(HTTP_DELETE,
1376 e5e20779 Faidon Liambotis
                             ("/%s/nodes/%s/tags" %
1377 e5e20779 Faidon Liambotis
                              (GANETI_RAPI_VERSION, node)), query, None)
1378 067dda99 Vangelis Koukis
1379 a3ad611d Dimitris Aragiorgis
  def GetNetworks(self, bulk=False):
1380 a3ad611d Dimitris Aragiorgis
    """Gets all networks in the cluster.
1381 a3ad611d Dimitris Aragiorgis

1382 a3ad611d Dimitris Aragiorgis
    @type bulk: bool
1383 a3ad611d Dimitris Aragiorgis
    @param bulk: whether to return all information about the networks
1384 a3ad611d Dimitris Aragiorgis

1385 a3ad611d Dimitris Aragiorgis
    @rtype: list of dict or str
1386 a3ad611d Dimitris Aragiorgis
    @return: if bulk is true, a list of dictionaries with info about all
1387 a3ad611d Dimitris Aragiorgis
        networks in the cluster, else a list of names of those networks
1388 a3ad611d Dimitris Aragiorgis

1389 a3ad611d Dimitris Aragiorgis
    """
1390 a3ad611d Dimitris Aragiorgis
    query = []
1391 a3ad611d Dimitris Aragiorgis
    _AppendIf(query, bulk, ("bulk", 1))
1392 a3ad611d Dimitris Aragiorgis
1393 a3ad611d Dimitris Aragiorgis
    networks = self._SendRequest(HTTP_GET, "/%s/networks" % GANETI_RAPI_VERSION,
1394 a3ad611d Dimitris Aragiorgis
                               query, None)
1395 a3ad611d Dimitris Aragiorgis
    if bulk:
1396 a3ad611d Dimitris Aragiorgis
      return networks
1397 a3ad611d Dimitris Aragiorgis
    else:
1398 a3ad611d Dimitris Aragiorgis
      return [n["name"] for n in networks]
1399 a3ad611d Dimitris Aragiorgis
1400 a3ad611d Dimitris Aragiorgis
  def GetNetwork(self, network):
1401 a3ad611d Dimitris Aragiorgis
    """Gets information about a network.
1402 a3ad611d Dimitris Aragiorgis

1403 a3ad611d Dimitris Aragiorgis
    @type group: str
1404 a3ad611d Dimitris Aragiorgis
    @param group: name of the network whose info to return
1405 a3ad611d Dimitris Aragiorgis

1406 a3ad611d Dimitris Aragiorgis
    @rtype: dict
1407 a3ad611d Dimitris Aragiorgis
    @return: info about the network
1408 a3ad611d Dimitris Aragiorgis

1409 a3ad611d Dimitris Aragiorgis
    """
1410 a3ad611d Dimitris Aragiorgis
    return self._SendRequest(HTTP_GET,
1411 a3ad611d Dimitris Aragiorgis
                             "/%s/networks/%s" % (GANETI_RAPI_VERSION, network),
1412 a3ad611d Dimitris Aragiorgis
                             None, None)
1413 a3ad611d Dimitris Aragiorgis
1414 a3ad611d Dimitris Aragiorgis
  def CreateNetwork(self, network_name, network, gateway=None, network6=None,
1415 9ef880a4 Dimitris Aragiorgis
                    gateway6=None, mac_prefix=None, network_type=None,
1416 a406663f Dimitris Aragiorgis
                    add_reserved_ips=None, tags=[],
1417 a406663f Dimitris Aragiorgis
                    conflicts_check=False, dry_run=False):
1418 a3ad611d Dimitris Aragiorgis
    """Creates a new network.
1419 a3ad611d Dimitris Aragiorgis

1420 a3ad611d Dimitris Aragiorgis
    @type name: str
1421 a3ad611d Dimitris Aragiorgis
    @param name: the name of network to create
1422 a3ad611d Dimitris Aragiorgis
    @type dry_run: bool
1423 a3ad611d Dimitris Aragiorgis
    @param dry_run: whether to peform a dry run
1424 a3ad611d Dimitris Aragiorgis

1425 a3ad611d Dimitris Aragiorgis
    @rtype: string
1426 a3ad611d Dimitris Aragiorgis
    @return: job id
1427 a3ad611d Dimitris Aragiorgis

1428 a3ad611d Dimitris Aragiorgis
    """
1429 a3ad611d Dimitris Aragiorgis
    query = []
1430 a3ad611d Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
1431 a3ad611d Dimitris Aragiorgis
1432 a3ad611d Dimitris Aragiorgis
    body = {
1433 a3ad611d Dimitris Aragiorgis
      "network_name": network_name,
1434 a3ad611d Dimitris Aragiorgis
      "gateway": gateway,
1435 a3ad611d Dimitris Aragiorgis
      "network": network,
1436 a3ad611d Dimitris Aragiorgis
      "gateway6": gateway6,
1437 a3ad611d Dimitris Aragiorgis
      "network6": network6,
1438 a3ad611d Dimitris Aragiorgis
      "mac_prefix": mac_prefix,
1439 9ef880a4 Dimitris Aragiorgis
      "network_type": network_type,
1440 a406663f Dimitris Aragiorgis
      "add_reserved_ips": add_reserved_ips,
1441 6de25206 Dimitris Aragiorgis
      "conflicts_check": conflicts_check,
1442 a406663f Dimitris Aragiorgis
      "tags": tags,
1443 a3ad611d Dimitris Aragiorgis
      }
1444 a3ad611d Dimitris Aragiorgis
1445 a3ad611d Dimitris Aragiorgis
    return self._SendRequest(HTTP_POST, "/%s/networks" % GANETI_RAPI_VERSION,
1446 a3ad611d Dimitris Aragiorgis
                             query, body)
1447 a3ad611d Dimitris Aragiorgis
1448 6de25206 Dimitris Aragiorgis
  def ConnectNetwork(self, network_name, group_name, mode, link,
1449 a406663f Dimitris Aragiorgis
                     conflicts_check=False, depends=None, dry_run=False):
1450 a3ad611d Dimitris Aragiorgis
    """Connects a Network to a NodeGroup with the given netparams
1451 a3ad611d Dimitris Aragiorgis

1452 a3ad611d Dimitris Aragiorgis
    """
1453 a3ad611d Dimitris Aragiorgis
    body = {
1454 a3ad611d Dimitris Aragiorgis
      "group_name": group_name,
1455 a3ad611d Dimitris Aragiorgis
      "network_mode": mode,
1456 6de25206 Dimitris Aragiorgis
      "network_link": link,
1457 6de25206 Dimitris Aragiorgis
      "conflicts_check": conflicts_check,
1458 a3ad611d Dimitris Aragiorgis
      }
1459 a3ad611d Dimitris Aragiorgis
1460 a3ad611d Dimitris Aragiorgis
    if depends:
1461 99af08a4 Christos Stavrakakis
      body['depends'] = depends
1462 a3ad611d Dimitris Aragiorgis
1463 a406663f Dimitris Aragiorgis
    query = []
1464 a406663f Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
1465 a3ad611d Dimitris Aragiorgis
1466 a3ad611d Dimitris Aragiorgis
    return self._SendRequest(HTTP_PUT,
1467 a3ad611d Dimitris Aragiorgis
                             ("/%s/networks/%s/connect" %
1468 a406663f Dimitris Aragiorgis
                             (GANETI_RAPI_VERSION, network_name)), query, body)
1469 a3ad611d Dimitris Aragiorgis
1470 a406663f Dimitris Aragiorgis
  def DisconnectNetwork(self, network_name, group_name,
1471 a406663f Dimitris Aragiorgis
                        depends=None, dry_run=False):
1472 a3ad611d Dimitris Aragiorgis
    """Connects a Network to a NodeGroup with the given netparams
1473 a3ad611d Dimitris Aragiorgis

1474 a3ad611d Dimitris Aragiorgis
    """
1475 a3ad611d Dimitris Aragiorgis
    body = {
1476 a3ad611d Dimitris Aragiorgis
      "group_name": group_name
1477 a3ad611d Dimitris Aragiorgis
      }
1478 a3ad611d Dimitris Aragiorgis
1479 a3ad611d Dimitris Aragiorgis
    if depends:
1480 99af08a4 Christos Stavrakakis
      body['depends'] = depends
1481 a3ad611d Dimitris Aragiorgis
1482 a406663f Dimitris Aragiorgis
    query = []
1483 a406663f Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
1484 a406663f Dimitris Aragiorgis
1485 a3ad611d Dimitris Aragiorgis
    return self._SendRequest(HTTP_PUT,
1486 a3ad611d Dimitris Aragiorgis
                             ("/%s/networks/%s/disconnect" %
1487 a406663f Dimitris Aragiorgis
                             (GANETI_RAPI_VERSION, network_name)), query, body)
1488 a406663f Dimitris Aragiorgis
1489 a406663f Dimitris Aragiorgis
1490 a406663f Dimitris Aragiorgis
  def ModifyNetwork(self, network, **kwargs):
1491 a406663f Dimitris Aragiorgis
    """Modifies a network.
1492 a406663f Dimitris Aragiorgis

1493 a406663f Dimitris Aragiorgis
    More details for parameters can be found in the RAPI documentation.
1494 a3ad611d Dimitris Aragiorgis

1495 a406663f Dimitris Aragiorgis
    @type network: string
1496 a406663f Dimitris Aragiorgis
    @param network: Network name
1497 a406663f Dimitris Aragiorgis
    @rtype: string
1498 a406663f Dimitris Aragiorgis
    @return: job id
1499 a3ad611d Dimitris Aragiorgis

1500 a406663f Dimitris Aragiorgis
    """
1501 a406663f Dimitris Aragiorgis
    return self._SendRequest(HTTP_PUT,
1502 a406663f Dimitris Aragiorgis
                             ("/%s/networks/%s/modify" %
1503 a406663f Dimitris Aragiorgis
                              (GANETI_RAPI_VERSION, network)), None, kwargs)
1504 a406663f Dimitris Aragiorgis
1505 a406663f Dimitris Aragiorgis
  def DeleteNetwork(self, network, depends=None, dry_run=False):
1506 a3ad611d Dimitris Aragiorgis
    """Deletes a network.
1507 a3ad611d Dimitris Aragiorgis

1508 a3ad611d Dimitris Aragiorgis
    @type group: str
1509 a3ad611d Dimitris Aragiorgis
    @param group: the network to delete
1510 a3ad611d Dimitris Aragiorgis
    @type dry_run: bool
1511 a3ad611d Dimitris Aragiorgis
    @param dry_run: whether to peform a dry run
1512 a3ad611d Dimitris Aragiorgis

1513 a3ad611d Dimitris Aragiorgis
    @rtype: string
1514 a3ad611d Dimitris Aragiorgis
    @return: job id
1515 a3ad611d Dimitris Aragiorgis

1516 a3ad611d Dimitris Aragiorgis
    """
1517 a3ad611d Dimitris Aragiorgis
    body = {}
1518 a3ad611d Dimitris Aragiorgis
    if depends:
1519 99af08a4 Christos Stavrakakis
      body['depends'] = depends
1520 a3ad611d Dimitris Aragiorgis
1521 a406663f Dimitris Aragiorgis
    query = []
1522 a406663f Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
1523 a3ad611d Dimitris Aragiorgis
1524 a3ad611d Dimitris Aragiorgis
    return self._SendRequest(HTTP_DELETE,
1525 a3ad611d Dimitris Aragiorgis
                             ("/%s/networks/%s" %
1526 a406663f Dimitris Aragiorgis
                              (GANETI_RAPI_VERSION, network)), query, body)
1527 a406663f Dimitris Aragiorgis
1528 a406663f Dimitris Aragiorgis
  def GetNetworkTags(self, network):
1529 a406663f Dimitris Aragiorgis
    """Gets tags for a network.
1530 a406663f Dimitris Aragiorgis

1531 a406663f Dimitris Aragiorgis
    @type network: string
1532 a406663f Dimitris Aragiorgis
    @param network: Node group whose tags to return
1533 a406663f Dimitris Aragiorgis

1534 a406663f Dimitris Aragiorgis
    @rtype: list of strings
1535 a406663f Dimitris Aragiorgis
    @return: tags for the network
1536 a406663f Dimitris Aragiorgis

1537 a406663f Dimitris Aragiorgis
    """
1538 a406663f Dimitris Aragiorgis
    return self._SendRequest(HTTP_GET,
1539 a406663f Dimitris Aragiorgis
                             ("/%s/networks/%s/tags" %
1540 a406663f Dimitris Aragiorgis
                              (GANETI_RAPI_VERSION, network)), None, None)
1541 a406663f Dimitris Aragiorgis
1542 a406663f Dimitris Aragiorgis
  def AddNetworkTags(self, network, tags, dry_run=False):
1543 a406663f Dimitris Aragiorgis
    """Adds tags to a network.
1544 a406663f Dimitris Aragiorgis

1545 a406663f Dimitris Aragiorgis
    @type network: str
1546 a406663f Dimitris Aragiorgis
    @param network: network to add tags to
1547 a406663f Dimitris Aragiorgis
    @type tags: list of string
1548 a406663f Dimitris Aragiorgis
    @param tags: tags to add to the network
1549 a406663f Dimitris Aragiorgis
    @type dry_run: bool
1550 a406663f Dimitris Aragiorgis
    @param dry_run: whether to perform a dry run
1551 a406663f Dimitris Aragiorgis

1552 a406663f Dimitris Aragiorgis
    @rtype: string
1553 a406663f Dimitris Aragiorgis
    @return: job id
1554 a406663f Dimitris Aragiorgis

1555 a406663f Dimitris Aragiorgis
    """
1556 a406663f Dimitris Aragiorgis
    query = [("tag", t) for t in tags]
1557 a406663f Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
1558 a406663f Dimitris Aragiorgis
1559 a406663f Dimitris Aragiorgis
    return self._SendRequest(HTTP_PUT,
1560 a406663f Dimitris Aragiorgis
                             ("/%s/networks/%s/tags" %
1561 a406663f Dimitris Aragiorgis
                              (GANETI_RAPI_VERSION, network)), query, None)
1562 a406663f Dimitris Aragiorgis
1563 a406663f Dimitris Aragiorgis
  def DeleteNetworkTags(self, network, tags, dry_run=False):
1564 a406663f Dimitris Aragiorgis
    """Deletes tags from a network.
1565 a406663f Dimitris Aragiorgis

1566 a406663f Dimitris Aragiorgis
    @type network: str
1567 a406663f Dimitris Aragiorgis
    @param network: network to delete tags from
1568 a406663f Dimitris Aragiorgis
    @type tags: list of string
1569 a406663f Dimitris Aragiorgis
    @param tags: tags to delete
1570 a406663f Dimitris Aragiorgis
    @type dry_run: bool
1571 a406663f Dimitris Aragiorgis
    @param dry_run: whether to perform a dry run
1572 a406663f Dimitris Aragiorgis
    @rtype: string
1573 a406663f Dimitris Aragiorgis
    @return: job id
1574 a406663f Dimitris Aragiorgis

1575 a406663f Dimitris Aragiorgis
    """
1576 a406663f Dimitris Aragiorgis
    query = [("tag", t) for t in tags]
1577 a406663f Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
1578 a406663f Dimitris Aragiorgis
1579 a406663f Dimitris Aragiorgis
    return self._SendRequest(HTTP_DELETE,
1580 a406663f Dimitris Aragiorgis
                             ("/%s/networks/%s/tags" %
1581 a406663f Dimitris Aragiorgis
                              (GANETI_RAPI_VERSION, network)), query, None)
1582 a406663f Dimitris Aragiorgis
1583 a3ad611d Dimitris Aragiorgis
1584 067dda99 Vangelis Koukis
  def GetGroups(self, bulk=False):
1585 067dda99 Vangelis Koukis
    """Gets all node groups in the cluster.
1586 067dda99 Vangelis Koukis

1587 067dda99 Vangelis Koukis
    @type bulk: bool
1588 067dda99 Vangelis Koukis
    @param bulk: whether to return all information about the groups
1589 067dda99 Vangelis Koukis

1590 067dda99 Vangelis Koukis
    @rtype: list of dict or str
1591 067dda99 Vangelis Koukis
    @return: if bulk is true, a list of dictionaries with info about all node
1592 067dda99 Vangelis Koukis
        groups in the cluster, else a list of names of those node groups
1593 067dda99 Vangelis Koukis

1594 067dda99 Vangelis Koukis
    """
1595 067dda99 Vangelis Koukis
    query = []
1596 a3ad611d Dimitris Aragiorgis
    _AppendIf(query, bulk, ("bulk", 1))
1597 067dda99 Vangelis Koukis
1598 067dda99 Vangelis Koukis
    groups = self._SendRequest(HTTP_GET, "/%s/groups" % GANETI_RAPI_VERSION,
1599 067dda99 Vangelis Koukis
                               query, None)
1600 067dda99 Vangelis Koukis
    if bulk:
1601 067dda99 Vangelis Koukis
      return groups
1602 067dda99 Vangelis Koukis
    else:
1603 067dda99 Vangelis Koukis
      return [g["name"] for g in groups]
1604 067dda99 Vangelis Koukis
1605 067dda99 Vangelis Koukis
  def GetGroup(self, group):
1606 067dda99 Vangelis Koukis
    """Gets information about a node group.
1607 067dda99 Vangelis Koukis

1608 067dda99 Vangelis Koukis
    @type group: str
1609 067dda99 Vangelis Koukis
    @param group: name of the node group whose info to return
1610 067dda99 Vangelis Koukis

1611 067dda99 Vangelis Koukis
    @rtype: dict
1612 067dda99 Vangelis Koukis
    @return: info about the node group
1613 067dda99 Vangelis Koukis

1614 067dda99 Vangelis Koukis
    """
1615 067dda99 Vangelis Koukis
    return self._SendRequest(HTTP_GET,
1616 067dda99 Vangelis Koukis
                             "/%s/groups/%s" % (GANETI_RAPI_VERSION, group),
1617 067dda99 Vangelis Koukis
                             None, None)
1618 067dda99 Vangelis Koukis
1619 067dda99 Vangelis Koukis
  def CreateGroup(self, name, alloc_policy=None, dry_run=False):
1620 067dda99 Vangelis Koukis
    """Creates a new node group.
1621 067dda99 Vangelis Koukis

1622 067dda99 Vangelis Koukis
    @type name: str
1623 067dda99 Vangelis Koukis
    @param name: the name of node group to create
1624 067dda99 Vangelis Koukis
    @type alloc_policy: str
1625 067dda99 Vangelis Koukis
    @param alloc_policy: the desired allocation policy for the group, if any
1626 067dda99 Vangelis Koukis
    @type dry_run: bool
1627 067dda99 Vangelis Koukis
    @param dry_run: whether to peform a dry run
1628 067dda99 Vangelis Koukis

1629 a3ad611d Dimitris Aragiorgis
    @rtype: string
1630 067dda99 Vangelis Koukis
    @return: job id
1631 067dda99 Vangelis Koukis

1632 067dda99 Vangelis Koukis
    """
1633 067dda99 Vangelis Koukis
    query = []
1634 a3ad611d Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
1635 067dda99 Vangelis Koukis
1636 067dda99 Vangelis Koukis
    body = {
1637 067dda99 Vangelis Koukis
      "name": name,
1638 067dda99 Vangelis Koukis
      "alloc_policy": alloc_policy
1639 067dda99 Vangelis Koukis
      }
1640 067dda99 Vangelis Koukis
1641 067dda99 Vangelis Koukis
    return self._SendRequest(HTTP_POST, "/%s/groups" % GANETI_RAPI_VERSION,
1642 067dda99 Vangelis Koukis
                             query, body)
1643 067dda99 Vangelis Koukis
1644 067dda99 Vangelis Koukis
  def ModifyGroup(self, group, **kwargs):
1645 067dda99 Vangelis Koukis
    """Modifies a node group.
1646 067dda99 Vangelis Koukis

1647 067dda99 Vangelis Koukis
    More details for parameters can be found in the RAPI documentation.
1648 067dda99 Vangelis Koukis

1649 067dda99 Vangelis Koukis
    @type group: string
1650 067dda99 Vangelis Koukis
    @param group: Node group name
1651 a3ad611d Dimitris Aragiorgis
    @rtype: string
1652 067dda99 Vangelis Koukis
    @return: job id
1653 067dda99 Vangelis Koukis

1654 067dda99 Vangelis Koukis
    """
1655 067dda99 Vangelis Koukis
    return self._SendRequest(HTTP_PUT,
1656 067dda99 Vangelis Koukis
                             ("/%s/groups/%s/modify" %
1657 067dda99 Vangelis Koukis
                              (GANETI_RAPI_VERSION, group)), None, kwargs)
1658 067dda99 Vangelis Koukis
1659 067dda99 Vangelis Koukis
  def DeleteGroup(self, group, dry_run=False):
1660 067dda99 Vangelis Koukis
    """Deletes a node group.
1661 067dda99 Vangelis Koukis

1662 067dda99 Vangelis Koukis
    @type group: str
1663 067dda99 Vangelis Koukis
    @param group: the node group to delete
1664 067dda99 Vangelis Koukis
    @type dry_run: bool
1665 067dda99 Vangelis Koukis
    @param dry_run: whether to peform a dry run
1666 067dda99 Vangelis Koukis

1667 a3ad611d Dimitris Aragiorgis
    @rtype: string
1668 067dda99 Vangelis Koukis
    @return: job id
1669 067dda99 Vangelis Koukis

1670 067dda99 Vangelis Koukis
    """
1671 067dda99 Vangelis Koukis
    query = []
1672 a3ad611d Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
1673 067dda99 Vangelis Koukis
1674 067dda99 Vangelis Koukis
    return self._SendRequest(HTTP_DELETE,
1675 067dda99 Vangelis Koukis
                             ("/%s/groups/%s" %
1676 067dda99 Vangelis Koukis
                              (GANETI_RAPI_VERSION, group)), query, None)
1677 067dda99 Vangelis Koukis
1678 067dda99 Vangelis Koukis
  def RenameGroup(self, group, new_name):
1679 067dda99 Vangelis Koukis
    """Changes the name of a node group.
1680 067dda99 Vangelis Koukis

1681 067dda99 Vangelis Koukis
    @type group: string
1682 067dda99 Vangelis Koukis
    @param group: Node group name
1683 067dda99 Vangelis Koukis
    @type new_name: string
1684 067dda99 Vangelis Koukis
    @param new_name: New node group name
1685 067dda99 Vangelis Koukis

1686 a3ad611d Dimitris Aragiorgis
    @rtype: string
1687 067dda99 Vangelis Koukis
    @return: job id
1688 067dda99 Vangelis Koukis

1689 067dda99 Vangelis Koukis
    """
1690 067dda99 Vangelis Koukis
    body = {
1691 067dda99 Vangelis Koukis
      "new_name": new_name,
1692 067dda99 Vangelis Koukis
      }
1693 067dda99 Vangelis Koukis
1694 067dda99 Vangelis Koukis
    return self._SendRequest(HTTP_PUT,
1695 067dda99 Vangelis Koukis
                             ("/%s/groups/%s/rename" %
1696 067dda99 Vangelis Koukis
                              (GANETI_RAPI_VERSION, group)), None, body)
1697 067dda99 Vangelis Koukis
1698 067dda99 Vangelis Koukis
  def AssignGroupNodes(self, group, nodes, force=False, dry_run=False):
1699 067dda99 Vangelis Koukis
    """Assigns nodes to a group.
1700 067dda99 Vangelis Koukis

1701 067dda99 Vangelis Koukis
    @type group: string
1702 067dda99 Vangelis Koukis
    @param group: Node gropu name
1703 067dda99 Vangelis Koukis
    @type nodes: list of strings
1704 067dda99 Vangelis Koukis
    @param nodes: List of nodes to assign to the group
1705 067dda99 Vangelis Koukis

1706 a3ad611d Dimitris Aragiorgis
    @rtype: string
1707 067dda99 Vangelis Koukis
    @return: job id
1708 067dda99 Vangelis Koukis

1709 067dda99 Vangelis Koukis
    """
1710 067dda99 Vangelis Koukis
    query = []
1711 a3ad611d Dimitris Aragiorgis
    _AppendForceIf(query, force)
1712 a3ad611d Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
1713 067dda99 Vangelis Koukis
1714 067dda99 Vangelis Koukis
    body = {
1715 067dda99 Vangelis Koukis
      "nodes": nodes,
1716 067dda99 Vangelis Koukis
      }
1717 067dda99 Vangelis Koukis
1718 067dda99 Vangelis Koukis
    return self._SendRequest(HTTP_PUT,
1719 067dda99 Vangelis Koukis
                             ("/%s/groups/%s/assign-nodes" %
1720 067dda99 Vangelis Koukis
                             (GANETI_RAPI_VERSION, group)), query, body)
1721 a3ad611d Dimitris Aragiorgis
1722 a3ad611d Dimitris Aragiorgis
  def GetGroupTags(self, group):
1723 a3ad611d Dimitris Aragiorgis
    """Gets tags for a node group.
1724 a3ad611d Dimitris Aragiorgis

1725 a3ad611d Dimitris Aragiorgis
    @type group: string
1726 a3ad611d Dimitris Aragiorgis
    @param group: Node group whose tags to return
1727 a3ad611d Dimitris Aragiorgis

1728 a3ad611d Dimitris Aragiorgis
    @rtype: list of strings
1729 a3ad611d Dimitris Aragiorgis
    @return: tags for the group
1730 a3ad611d Dimitris Aragiorgis

1731 a3ad611d Dimitris Aragiorgis
    """
1732 a3ad611d Dimitris Aragiorgis
    return self._SendRequest(HTTP_GET,
1733 a3ad611d Dimitris Aragiorgis
                             ("/%s/groups/%s/tags" %
1734 a3ad611d Dimitris Aragiorgis
                              (GANETI_RAPI_VERSION, group)), None, None)
1735 a3ad611d Dimitris Aragiorgis
1736 a3ad611d Dimitris Aragiorgis
  def AddGroupTags(self, group, tags, dry_run=False):
1737 a3ad611d Dimitris Aragiorgis
    """Adds tags to a node group.
1738 a3ad611d Dimitris Aragiorgis

1739 a3ad611d Dimitris Aragiorgis
    @type group: str
1740 a3ad611d Dimitris Aragiorgis
    @param group: group to add tags to
1741 a3ad611d Dimitris Aragiorgis
    @type tags: list of string
1742 a3ad611d Dimitris Aragiorgis
    @param tags: tags to add to the group
1743 a3ad611d Dimitris Aragiorgis
    @type dry_run: bool
1744 a3ad611d Dimitris Aragiorgis
    @param dry_run: whether to perform a dry run
1745 a3ad611d Dimitris Aragiorgis

1746 a3ad611d Dimitris Aragiorgis
    @rtype: string
1747 a3ad611d Dimitris Aragiorgis
    @return: job id
1748 a3ad611d Dimitris Aragiorgis

1749 a3ad611d Dimitris Aragiorgis
    """
1750 a3ad611d Dimitris Aragiorgis
    query = [("tag", t) for t in tags]
1751 a3ad611d Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
1752 a3ad611d Dimitris Aragiorgis
1753 a3ad611d Dimitris Aragiorgis
    return self._SendRequest(HTTP_PUT,
1754 a3ad611d Dimitris Aragiorgis
                             ("/%s/groups/%s/tags" %
1755 a3ad611d Dimitris Aragiorgis
                              (GANETI_RAPI_VERSION, group)), query, None)
1756 a3ad611d Dimitris Aragiorgis
1757 a3ad611d Dimitris Aragiorgis
  def DeleteGroupTags(self, group, tags, dry_run=False):
1758 a3ad611d Dimitris Aragiorgis
    """Deletes tags from a node group.
1759 a3ad611d Dimitris Aragiorgis

1760 a3ad611d Dimitris Aragiorgis
    @type group: str
1761 a3ad611d Dimitris Aragiorgis
    @param group: group to delete tags from
1762 a3ad611d Dimitris Aragiorgis
    @type tags: list of string
1763 a3ad611d Dimitris Aragiorgis
    @param tags: tags to delete
1764 a3ad611d Dimitris Aragiorgis
    @type dry_run: bool
1765 a3ad611d Dimitris Aragiorgis
    @param dry_run: whether to perform a dry run
1766 a3ad611d Dimitris Aragiorgis
    @rtype: string
1767 a3ad611d Dimitris Aragiorgis
    @return: job id
1768 a3ad611d Dimitris Aragiorgis

1769 a3ad611d Dimitris Aragiorgis
    """
1770 a3ad611d Dimitris Aragiorgis
    query = [("tag", t) for t in tags]
1771 a3ad611d Dimitris Aragiorgis
    _AppendDryRunIf(query, dry_run)
1772 a3ad611d Dimitris Aragiorgis
1773 a3ad611d Dimitris Aragiorgis
    return self._SendRequest(HTTP_DELETE,
1774 a3ad611d Dimitris Aragiorgis
                             ("/%s/groups/%s/tags" %
1775 a3ad611d Dimitris Aragiorgis
                              (GANETI_RAPI_VERSION, group)), query, None)
1776 a3ad611d Dimitris Aragiorgis
1777 a3ad611d Dimitris Aragiorgis
  def Query(self, what, fields, qfilter=None):
1778 a3ad611d Dimitris Aragiorgis
    """Retrieves information about resources.
1779 a3ad611d Dimitris Aragiorgis

1780 a3ad611d Dimitris Aragiorgis
    @type what: string
1781 a3ad611d Dimitris Aragiorgis
    @param what: Resource name, one of L{constants.QR_VIA_RAPI}
1782 a3ad611d Dimitris Aragiorgis
    @type fields: list of string
1783 a3ad611d Dimitris Aragiorgis
    @param fields: Requested fields
1784 a3ad611d Dimitris Aragiorgis
    @type qfilter: None or list
1785 a3ad611d Dimitris Aragiorgis
    @param qfilter: Query filter
1786 a3ad611d Dimitris Aragiorgis

1787 a3ad611d Dimitris Aragiorgis
    @rtype: string
1788 a3ad611d Dimitris Aragiorgis
    @return: job id
1789 a3ad611d Dimitris Aragiorgis

1790 a3ad611d Dimitris Aragiorgis
    """
1791 a3ad611d Dimitris Aragiorgis
    body = {
1792 a3ad611d Dimitris Aragiorgis
      "fields": fields,
1793 a3ad611d Dimitris Aragiorgis
      }
1794 a3ad611d Dimitris Aragiorgis
1795 a3ad611d Dimitris Aragiorgis
    _SetItemIf(body, qfilter is not None, "qfilter", qfilter)
1796 a3ad611d Dimitris Aragiorgis
    # TODO: remove "filter" after 2.7
1797 a3ad611d Dimitris Aragiorgis
    _SetItemIf(body, qfilter is not None, "filter", qfilter)
1798 a3ad611d Dimitris Aragiorgis
1799 a3ad611d Dimitris Aragiorgis
    return self._SendRequest(HTTP_PUT,
1800 a3ad611d Dimitris Aragiorgis
                             ("/%s/query/%s" %
1801 a3ad611d Dimitris Aragiorgis
                              (GANETI_RAPI_VERSION, what)), None, body)
1802 a3ad611d Dimitris Aragiorgis
1803 a3ad611d Dimitris Aragiorgis
  def QueryFields(self, what, fields=None):
1804 a3ad611d Dimitris Aragiorgis
    """Retrieves available fields for a resource.
1805 a3ad611d Dimitris Aragiorgis

1806 a3ad611d Dimitris Aragiorgis
    @type what: string
1807 a3ad611d Dimitris Aragiorgis
    @param what: Resource name, one of L{constants.QR_VIA_RAPI}
1808 a3ad611d Dimitris Aragiorgis
    @type fields: list of string
1809 a3ad611d Dimitris Aragiorgis
    @param fields: Requested fields
1810 a3ad611d Dimitris Aragiorgis

1811 a3ad611d Dimitris Aragiorgis
    @rtype: string
1812 a3ad611d Dimitris Aragiorgis
    @return: job id
1813 a3ad611d Dimitris Aragiorgis

1814 a3ad611d Dimitris Aragiorgis
    """
1815 a3ad611d Dimitris Aragiorgis
    query = []
1816 a3ad611d Dimitris Aragiorgis
1817 a3ad611d Dimitris Aragiorgis
    if fields is not None:
1818 a3ad611d Dimitris Aragiorgis
      _AppendIf(query, True, ("fields", ",".join(fields)))
1819 a3ad611d Dimitris Aragiorgis
1820 a3ad611d Dimitris Aragiorgis
    return self._SendRequest(HTTP_GET,
1821 a3ad611d Dimitris Aragiorgis
                             ("/%s/query/%s/fields" %
1822 a3ad611d Dimitris Aragiorgis
                              (GANETI_RAPI_VERSION, what)), query, None)