Statistics
| Branch: | Tag: | Revision:

root / qa / qa_rapi.py @ 82ce55fa

History | View | Annotate | Download (25.5 kB)

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

24 a47f574c Oleksiy Mishchenko
"""
25 a47f574c Oleksiy Mishchenko
26 2771835c Michael Hanselmann
import tempfile
27 4fab7cab Michael Hanselmann
import random
28 c1513c7f Michael Hanselmann
import re
29 c1513c7f Michael Hanselmann
import itertools
30 a47f574c Oleksiy Mishchenko
31 a47f574c Oleksiy Mishchenko
from ganeti import utils
32 a47f574c Oleksiy Mishchenko
from ganeti import constants
33 a47f574c Oleksiy Mishchenko
from ganeti import errors
34 2771835c Michael Hanselmann
from ganeti import cli
35 2771835c Michael Hanselmann
from ganeti import rapi
36 b82d4c5e Michael Hanselmann
from ganeti import objects
37 4fab7cab Michael Hanselmann
from ganeti import query
38 4fab7cab Michael Hanselmann
from ganeti import compat
39 4fab7cab Michael Hanselmann
from ganeti import qlang
40 304d9f02 Michael Hanselmann
from ganeti import pathutils
41 2771835c Michael Hanselmann
42 fcd2359a Hrvoje Ribicic
from ganeti.http.auth import ParsePasswordFile
43 b459a848 Andrea Spadaccini
import ganeti.rapi.client        # pylint: disable=W0611
44 2771835c Michael Hanselmann
import ganeti.rapi.client_utils
45 a47f574c Oleksiy Mishchenko
46 a47f574c Oleksiy Mishchenko
import qa_config
47 a47f574c Oleksiy Mishchenko
import qa_utils
48 a47f574c Oleksiy Mishchenko
import qa_error
49 a47f574c Oleksiy Mishchenko
50 5de31440 Bernardo Dal Seno
from qa_instance import IsFailoverSupported
51 5de31440 Bernardo Dal Seno
from qa_instance import IsMigrationSupported
52 5de31440 Bernardo Dal Seno
from qa_instance import IsDiskReplacingSupported
53 3582eef6 Iustin Pop
from qa_utils import (AssertEqual, AssertIn, AssertMatch, StartLocalCommand)
54 5fa0375e Michael Hanselmann
from qa_utils import InstanceCheck, INST_DOWN, INST_UP, FIRST_ARG
55 a47f574c Oleksiy Mishchenko
56 a47f574c Oleksiy Mishchenko
57 2771835c Michael Hanselmann
_rapi_ca = None
58 2771835c Michael Hanselmann
_rapi_client = None
59 5d831182 Michael Hanselmann
_rapi_username = None
60 5d831182 Michael Hanselmann
_rapi_password = None
61 e6ce18ac René Nussbaumer
62 e6ce18ac René Nussbaumer
63 2771835c Michael Hanselmann
def Setup(username, password):
64 2771835c Michael Hanselmann
  """Configures the RAPI client.
65 725ec2f1 René Nussbaumer

66 2771835c Michael Hanselmann
  """
67 b459a848 Andrea Spadaccini
  # pylint: disable=W0603
68 3582eef6 Iustin Pop
  # due to global usage
69 2771835c Michael Hanselmann
  global _rapi_ca
70 2771835c Michael Hanselmann
  global _rapi_client
71 5d831182 Michael Hanselmann
  global _rapi_username
72 5d831182 Michael Hanselmann
  global _rapi_password
73 5d831182 Michael Hanselmann
74 5d831182 Michael Hanselmann
  _rapi_username = username
75 5d831182 Michael Hanselmann
  _rapi_password = password
76 e6ce18ac René Nussbaumer
77 2771835c Michael Hanselmann
  master = qa_config.GetMasterNode()
78 e6ce18ac René Nussbaumer
79 2771835c Michael Hanselmann
  # Load RAPI certificate from master node
80 dcd85eef Michael Hanselmann
  cmd = ["cat", qa_utils.MakeNodePath(master, pathutils.RAPI_CERT_FILE)]
81 e6ce18ac René Nussbaumer
82 2771835c Michael Hanselmann
  # Write to temporary file
83 2771835c Michael Hanselmann
  _rapi_ca = tempfile.NamedTemporaryFile()
84 aecba21e Michael Hanselmann
  _rapi_ca.write(qa_utils.GetCommandOutput(master.primary,
85 2771835c Michael Hanselmann
                                           utils.ShellQuoteArgs(cmd)))
86 2771835c Michael Hanselmann
  _rapi_ca.flush()
87 e6ce18ac René Nussbaumer
88 2771835c Michael Hanselmann
  port = qa_config.get("rapi-port", default=constants.DEFAULT_RAPI_PORT)
89 2a7c3583 Michael Hanselmann
  cfg_curl = rapi.client.GenericCurlConfig(cafile=_rapi_ca.name,
90 2a7c3583 Michael Hanselmann
                                           proxy="")
91 e6ce18ac René Nussbaumer
92 301adaae Michael Hanselmann
  if qa_config.UseVirtualCluster():
93 301adaae Michael Hanselmann
    # TODO: Implement full support for RAPI on virtual clusters
94 301adaae Michael Hanselmann
    print qa_utils.FormatWarning("RAPI tests are not yet supported on"
95 301adaae Michael Hanselmann
                                 " virtual clusters and will be disabled")
96 e6ce18ac René Nussbaumer
97 301adaae Michael Hanselmann
    assert _rapi_client is None
98 301adaae Michael Hanselmann
  else:
99 301adaae Michael Hanselmann
    _rapi_client = rapi.client.GanetiRapiClient(master.primary, port=port,
100 301adaae Michael Hanselmann
                                                username=username,
101 301adaae Michael Hanselmann
                                                password=password,
102 301adaae Michael Hanselmann
                                                curl_config_fn=cfg_curl)
103 301adaae Michael Hanselmann
104 301adaae Michael Hanselmann
    print "RAPI protocol version: %s" % _rapi_client.GetVersion()
105 a47f574c Oleksiy Mishchenko
106 a784d28c Hrvoje Ribicic
  return _rapi_client
107 a784d28c Hrvoje Ribicic
108 a47f574c Oleksiy Mishchenko
109 fcd2359a Hrvoje Ribicic
def LookupRapiSecret(rapi_user):
110 fcd2359a Hrvoje Ribicic
  """Find the RAPI secret for the given user.
111 fcd2359a Hrvoje Ribicic

112 fcd2359a Hrvoje Ribicic
  @param rapi_user: Login user
113 fcd2359a Hrvoje Ribicic
  @return: Login secret for the user
114 fcd2359a Hrvoje Ribicic

115 fcd2359a Hrvoje Ribicic
  """
116 fcd2359a Hrvoje Ribicic
  CTEXT = "{CLEARTEXT}"
117 fcd2359a Hrvoje Ribicic
  master = qa_config.GetMasterNode()
118 fcd2359a Hrvoje Ribicic
  cmd = ["cat", qa_utils.MakeNodePath(master, pathutils.RAPI_USERS_FILE)]
119 fcd2359a Hrvoje Ribicic
  file_content = qa_utils.GetCommandOutput(master.primary,
120 fcd2359a Hrvoje Ribicic
                                           utils.ShellQuoteArgs(cmd))
121 fcd2359a Hrvoje Ribicic
  users = ParsePasswordFile(file_content)
122 fcd2359a Hrvoje Ribicic
  entry = users.get(rapi_user)
123 fcd2359a Hrvoje Ribicic
  if not entry:
124 fcd2359a Hrvoje Ribicic
    raise qa_error.Error("User %s not found in RAPI users file" % rapi_user)
125 fcd2359a Hrvoje Ribicic
  secret = entry.password
126 fcd2359a Hrvoje Ribicic
  if secret.upper().startswith(CTEXT):
127 fcd2359a Hrvoje Ribicic
    secret = secret[len(CTEXT):]
128 fcd2359a Hrvoje Ribicic
  elif secret.startswith("{"):
129 fcd2359a Hrvoje Ribicic
    raise qa_error.Error("Unsupported password schema for RAPI user %s:"
130 fcd2359a Hrvoje Ribicic
                         " not a clear text password" % rapi_user)
131 fcd2359a Hrvoje Ribicic
  return secret
132 fcd2359a Hrvoje Ribicic
133 fcd2359a Hrvoje Ribicic
134 a47f574c Oleksiy Mishchenko
INSTANCE_FIELDS = ("name", "os", "pnode", "snodes",
135 a5b9d725 Iustin Pop
                   "admin_state",
136 0e514de1 Bernardo Dal Seno
                   "disk_template", "disk.sizes", "disk.spindles",
137 22482387 Iustin Pop
                   "nic.ips", "nic.macs", "nic.modes", "nic.links",
138 a5b9d725 Iustin Pop
                   "beparams", "hvparams",
139 4ea3de4e Balazs Lecz
                   "oper_state", "oper_ram", "oper_vcpus", "status", "tags")
140 a47f574c Oleksiy Mishchenko
141 06fb92cf Bernardo Dal Seno
NODE_FIELDS = ("name", "dtotal", "dfree", "sptotal", "spfree",
142 a47f574c Oleksiy Mishchenko
               "mtotal", "mnode", "mfree",
143 a47f574c Oleksiy Mishchenko
               "pinst_cnt", "sinst_cnt", "tags")
144 a47f574c Oleksiy Mishchenko
145 b8028dcf Michael Hanselmann
GROUP_FIELDS = compat.UniqueFrozenset([
146 30131294 Adeodato Simo
  "name", "uuid",
147 90e99856 Adeodato Simo
  "alloc_policy",
148 30131294 Adeodato Simo
  "node_cnt", "node_list",
149 30131294 Adeodato Simo
  ])
150 30131294 Adeodato Simo
151 b8028dcf Michael Hanselmann
JOB_FIELDS = compat.UniqueFrozenset([
152 94e63ca1 Michael Hanselmann
  "id", "ops", "status", "summary",
153 94e63ca1 Michael Hanselmann
  "opstatus", "opresult", "oplog",
154 94e63ca1 Michael Hanselmann
  "received_ts", "start_ts", "end_ts",
155 94e63ca1 Michael Hanselmann
  ])
156 94e63ca1 Michael Hanselmann
157 68289c75 Iustin Pop
LIST_FIELDS = ("id", "uri")
158 a47f574c Oleksiy Mishchenko
159 a47f574c Oleksiy Mishchenko
160 a47f574c Oleksiy Mishchenko
def Enabled():
161 a47f574c Oleksiy Mishchenko
  """Return whether remote API tests should be run.
162 a47f574c Oleksiy Mishchenko

163 a47f574c Oleksiy Mishchenko
  """
164 301adaae Michael Hanselmann
  # TODO: Implement RAPI tests for virtual clusters
165 301adaae Michael Hanselmann
  return (qa_config.TestEnabled("rapi") and
166 301adaae Michael Hanselmann
          not qa_config.UseVirtualCluster())
167 a47f574c Oleksiy Mishchenko
168 a47f574c Oleksiy Mishchenko
169 a47f574c Oleksiy Mishchenko
def _DoTests(uris):
170 b459a848 Andrea Spadaccini
  # pylint: disable=W0212
171 3582eef6 Iustin Pop
  # due to _SendRequest usage
172 94e63ca1 Michael Hanselmann
  results = []
173 a47f574c Oleksiy Mishchenko
174 94e63ca1 Michael Hanselmann
  for uri, verify, method, body in uris:
175 a47f574c Oleksiy Mishchenko
    assert uri.startswith("/")
176 a47f574c Oleksiy Mishchenko
177 c326b4ef Michael Hanselmann
    print "%s %s" % (method, uri)
178 2771835c Michael Hanselmann
    data = _rapi_client._SendRequest(method, uri, None, body)
179 a47f574c Oleksiy Mishchenko
180 a47f574c Oleksiy Mishchenko
    if verify is not None:
181 a47f574c Oleksiy Mishchenko
      if callable(verify):
182 a47f574c Oleksiy Mishchenko
        verify(data)
183 a47f574c Oleksiy Mishchenko
      else:
184 a47f574c Oleksiy Mishchenko
        AssertEqual(data, verify)
185 a47f574c Oleksiy Mishchenko
186 fd837171 Michael Hanselmann
    results.append(data)
187 94e63ca1 Michael Hanselmann
188 94e63ca1 Michael Hanselmann
  return results
189 94e63ca1 Michael Hanselmann
190 94e63ca1 Michael Hanselmann
191 94e63ca1 Michael Hanselmann
def _VerifyReturnsJob(data):
192 76b62028 Iustin Pop
  if not isinstance(data, int):
193 76b62028 Iustin Pop
    AssertMatch(data, r"^\d+$")
194 94e63ca1 Michael Hanselmann
195 a47f574c Oleksiy Mishchenko
196 a47f574c Oleksiy Mishchenko
def TestVersion():
197 a47f574c Oleksiy Mishchenko
  """Testing remote API version.
198 a47f574c Oleksiy Mishchenko

199 a47f574c Oleksiy Mishchenko
  """
200 a47f574c Oleksiy Mishchenko
  _DoTests([
201 d0c8c01d Iustin Pop
    ("/version", constants.RAPI_VERSION, "GET", None),
202 a47f574c Oleksiy Mishchenko
    ])
203 a47f574c Oleksiy Mishchenko
204 a47f574c Oleksiy Mishchenko
205 a47f574c Oleksiy Mishchenko
def TestEmptyCluster():
206 a47f574c Oleksiy Mishchenko
  """Testing remote API on an empty cluster.
207 a47f574c Oleksiy Mishchenko

208 a47f574c Oleksiy Mishchenko
  """
209 94e63ca1 Michael Hanselmann
  master = qa_config.GetMasterNode()
210 94e63ca1 Michael Hanselmann
  master_full = qa_utils.ResolveNodeName(master)
211 a47f574c Oleksiy Mishchenko
212 a47f574c Oleksiy Mishchenko
  def _VerifyInfo(data):
213 a47f574c Oleksiy Mishchenko
    AssertIn("name", data)
214 a47f574c Oleksiy Mishchenko
    AssertIn("master", data)
215 94e63ca1 Michael Hanselmann
    AssertEqual(data["master"], master_full)
216 a47f574c Oleksiy Mishchenko
217 a47f574c Oleksiy Mishchenko
  def _VerifyNodes(data):
218 a47f574c Oleksiy Mishchenko
    master_entry = {
219 94e63ca1 Michael Hanselmann
      "id": master_full,
220 94e63ca1 Michael Hanselmann
      "uri": "/2/nodes/%s" % master_full,
221 a47f574c Oleksiy Mishchenko
      }
222 a47f574c Oleksiy Mishchenko
    AssertIn(master_entry, data)
223 a47f574c Oleksiy Mishchenko
224 a47f574c Oleksiy Mishchenko
  def _VerifyNodesBulk(data):
225 a47f574c Oleksiy Mishchenko
    for node in data:
226 a47f574c Oleksiy Mishchenko
      for entry in NODE_FIELDS:
227 a47f574c Oleksiy Mishchenko
        AssertIn(entry, node)
228 a47f574c Oleksiy Mishchenko
229 30131294 Adeodato Simo
  def _VerifyGroups(data):
230 30131294 Adeodato Simo
    default_group = {
231 75cf411a Adeodato Simo
      "name": constants.INITIAL_NODE_GROUP_NAME,
232 75cf411a Adeodato Simo
      "uri": "/2/groups/" + constants.INITIAL_NODE_GROUP_NAME,
233 30131294 Adeodato Simo
      }
234 30131294 Adeodato Simo
    AssertIn(default_group, data)
235 30131294 Adeodato Simo
236 30131294 Adeodato Simo
  def _VerifyGroupsBulk(data):
237 30131294 Adeodato Simo
    for group in data:
238 30131294 Adeodato Simo
      for field in GROUP_FIELDS:
239 30131294 Adeodato Simo
        AssertIn(field, group)
240 30131294 Adeodato Simo
241 a47f574c Oleksiy Mishchenko
  _DoTests([
242 d0c8c01d Iustin Pop
    ("/", None, "GET", None),
243 d0c8c01d Iustin Pop
    ("/2/info", _VerifyInfo, "GET", None),
244 d0c8c01d Iustin Pop
    ("/2/tags", None, "GET", None),
245 d0c8c01d Iustin Pop
    ("/2/nodes", _VerifyNodes, "GET", None),
246 d0c8c01d Iustin Pop
    ("/2/nodes?bulk=1", _VerifyNodesBulk, "GET", None),
247 d0c8c01d Iustin Pop
    ("/2/groups", _VerifyGroups, "GET", None),
248 d0c8c01d Iustin Pop
    ("/2/groups?bulk=1", _VerifyGroupsBulk, "GET", None),
249 d0c8c01d Iustin Pop
    ("/2/instances", [], "GET", None),
250 d0c8c01d Iustin Pop
    ("/2/instances?bulk=1", [], "GET", None),
251 d0c8c01d Iustin Pop
    ("/2/os", None, "GET", None),
252 a47f574c Oleksiy Mishchenko
    ])
253 a47f574c Oleksiy Mishchenko
254 4d2bd00a Michael Hanselmann
  # Test HTTP Not Found
255 4d2bd00a Michael Hanselmann
  for method in ["GET", "PUT", "POST", "DELETE"]:
256 4d2bd00a Michael Hanselmann
    try:
257 4d2bd00a Michael Hanselmann
      _DoTests([("/99/resource/not/here/99", None, method, None)])
258 4d2bd00a Michael Hanselmann
    except rapi.client.GanetiApiError, err:
259 4d2bd00a Michael Hanselmann
      AssertEqual(err.code, 404)
260 4d2bd00a Michael Hanselmann
    else:
261 4d2bd00a Michael Hanselmann
      raise qa_error.Error("Non-existent resource didn't return HTTP 404")
262 4d2bd00a Michael Hanselmann
263 4d2bd00a Michael Hanselmann
  # Test HTTP Not Implemented
264 4d2bd00a Michael Hanselmann
  for method in ["PUT", "POST", "DELETE"]:
265 4d2bd00a Michael Hanselmann
    try:
266 4d2bd00a Michael Hanselmann
      _DoTests([("/version", None, method, None)])
267 4d2bd00a Michael Hanselmann
    except rapi.client.GanetiApiError, err:
268 4d2bd00a Michael Hanselmann
      AssertEqual(err.code, 501)
269 4d2bd00a Michael Hanselmann
    else:
270 4d2bd00a Michael Hanselmann
      raise qa_error.Error("Non-implemented method didn't fail")
271 4d2bd00a Michael Hanselmann
272 a47f574c Oleksiy Mishchenko
273 4fab7cab Michael Hanselmann
def TestRapiQuery():
274 4fab7cab Michael Hanselmann
  """Testing resource queries via remote API.
275 4fab7cab Michael Hanselmann

276 4fab7cab Michael Hanselmann
  """
277 bab4f56a Helga Velroyen
  # FIXME: the tests are failing if no LVM is enabled, investigate
278 bab4f56a Helga Velroyen
  # if it is a bug in the QA or in the code
279 bab4f56a Helga Velroyen
  if not qa_config.IsStorageTypeSupported(constants.ST_LVM_VG):
280 bab4f56a Helga Velroyen
    return
281 bab4f56a Helga Velroyen
282 4fab7cab Michael Hanselmann
  master_name = qa_utils.ResolveNodeName(qa_config.GetMasterNode())
283 4fab7cab Michael Hanselmann
  rnd = random.Random(7818)
284 4fab7cab Michael Hanselmann
285 4fab7cab Michael Hanselmann
  for what in constants.QR_VIA_RAPI:
286 4faa4861 Iustin Pop
    if what == constants.QR_JOB:
287 4faa4861 Iustin Pop
      namefield = "id"
288 b5ae26cd Klaus Aehlig
      trivial_filter = [qlang.OP_GE, namefield, 0]
289 496d5ac8 Michael Hanselmann
    elif what == constants.QR_EXPORT:
290 496d5ac8 Michael Hanselmann
      namefield = "export"
291 b5ae26cd Klaus Aehlig
      trivial_filter = [qlang.OP_REGEXP, ".*", namefield]
292 4faa4861 Iustin Pop
    else:
293 4faa4861 Iustin Pop
      namefield = "name"
294 b5ae26cd Klaus Aehlig
      trivial_filter = [qlang.OP_REGEXP, ".*", namefield]
295 4faa4861 Iustin Pop
296 4fab7cab Michael Hanselmann
    all_fields = query.ALL_FIELDS[what].keys()
297 4fab7cab Michael Hanselmann
    rnd.shuffle(all_fields)
298 4fab7cab Michael Hanselmann
299 4fab7cab Michael Hanselmann
    # No fields, should return everything
300 4fab7cab Michael Hanselmann
    result = _rapi_client.QueryFields(what)
301 4fab7cab Michael Hanselmann
    qresult = objects.QueryFieldsResponse.FromDict(result)
302 4fab7cab Michael Hanselmann
    AssertEqual(len(qresult.fields), len(all_fields))
303 4fab7cab Michael Hanselmann
304 4fab7cab Michael Hanselmann
    # One field
305 4faa4861 Iustin Pop
    result = _rapi_client.QueryFields(what, fields=[namefield])
306 4fab7cab Michael Hanselmann
    qresult = objects.QueryFieldsResponse.FromDict(result)
307 4fab7cab Michael Hanselmann
    AssertEqual(len(qresult.fields), 1)
308 4fab7cab Michael Hanselmann
309 4fab7cab Michael Hanselmann
    # Specify all fields, order must be correct
310 4fab7cab Michael Hanselmann
    result = _rapi_client.QueryFields(what, fields=all_fields)
311 4fab7cab Michael Hanselmann
    qresult = objects.QueryFieldsResponse.FromDict(result)
312 4fab7cab Michael Hanselmann
    AssertEqual(len(qresult.fields), len(all_fields))
313 4fab7cab Michael Hanselmann
    AssertEqual([fdef.name for fdef in qresult.fields], all_fields)
314 4fab7cab Michael Hanselmann
315 4fab7cab Michael Hanselmann
    # Unknown field
316 4fab7cab Michael Hanselmann
    result = _rapi_client.QueryFields(what, fields=["_unknown!"])
317 4fab7cab Michael Hanselmann
    qresult = objects.QueryFieldsResponse.FromDict(result)
318 4fab7cab Michael Hanselmann
    AssertEqual(len(qresult.fields), 1)
319 4fab7cab Michael Hanselmann
    AssertEqual(qresult.fields[0].name, "_unknown!")
320 4fab7cab Michael Hanselmann
    AssertEqual(qresult.fields[0].kind, constants.QFT_UNKNOWN)
321 4fab7cab Michael Hanselmann
322 4fab7cab Michael Hanselmann
    # Try once more, this time without the client
323 4fab7cab Michael Hanselmann
    _DoTests([
324 4fab7cab Michael Hanselmann
      ("/2/query/%s/fields" % what, None, "GET", None),
325 4fab7cab Michael Hanselmann
      ("/2/query/%s/fields?fields=name,name,%s" % (what, all_fields[0]),
326 4fab7cab Michael Hanselmann
       None, "GET", None),
327 4fab7cab Michael Hanselmann
      ])
328 4fab7cab Michael Hanselmann
329 4fab7cab Michael Hanselmann
    # Try missing query argument
330 4fab7cab Michael Hanselmann
    try:
331 4fab7cab Michael Hanselmann
      _DoTests([
332 4fab7cab Michael Hanselmann
        ("/2/query/%s" % what, None, "GET", None),
333 4fab7cab Michael Hanselmann
        ])
334 4fab7cab Michael Hanselmann
    except rapi.client.GanetiApiError, err:
335 4fab7cab Michael Hanselmann
      AssertEqual(err.code, 400)
336 4fab7cab Michael Hanselmann
    else:
337 4fab7cab Michael Hanselmann
      raise qa_error.Error("Request missing 'fields' parameter didn't fail")
338 4fab7cab Michael Hanselmann
339 4fab7cab Michael Hanselmann
    def _Check(exp_fields, data):
340 4fab7cab Michael Hanselmann
      qresult = objects.QueryResponse.FromDict(data)
341 4fab7cab Michael Hanselmann
      AssertEqual([fdef.name for fdef in qresult.fields], exp_fields)
342 4fab7cab Michael Hanselmann
      if not isinstance(qresult.data, list):
343 4fab7cab Michael Hanselmann
        raise qa_error.Error("Query did not return a list")
344 4fab7cab Michael Hanselmann
345 4fab7cab Michael Hanselmann
    _DoTests([
346 4fab7cab Michael Hanselmann
      # Specify fields in query
347 4fab7cab Michael Hanselmann
      ("/2/query/%s?fields=%s" % (what, ",".join(all_fields)),
348 4fab7cab Michael Hanselmann
       compat.partial(_Check, all_fields), "GET", None),
349 4fab7cab Michael Hanselmann
350 4faa4861 Iustin Pop
      ("/2/query/%s?fields=%s" % (what, namefield),
351 4faa4861 Iustin Pop
       compat.partial(_Check, [namefield]), "GET", None),
352 4fab7cab Michael Hanselmann
353 4fab7cab Michael Hanselmann
      # Note the spaces
354 4faa4861 Iustin Pop
      ("/2/query/%s?fields=%s,%%20%s%%09,%s%%20" %
355 4faa4861 Iustin Pop
       (what, namefield, namefield, namefield),
356 cfb3116d Helga Velroyen
       compat.partial(_Check, [namefield] * 3), "GET", None)])
357 4fab7cab Michael Hanselmann
358 cfb3116d Helga Velroyen
    if what in constants.QR_VIA_RAPI_PUT:
359 cfb3116d Helga Velroyen
      _DoTests([
360 cfb3116d Helga Velroyen
        # PUT with fields in query
361 cfb3116d Helga Velroyen
        ("/2/query/%s?fields=%s" % (what, namefield),
362 cfb3116d Helga Velroyen
         compat.partial(_Check, [namefield]), "PUT", {}),
363 4fab7cab Michael Hanselmann
364 cfb3116d Helga Velroyen
        ("/2/query/%s" % what, compat.partial(_Check, [namefield] * 4), "PUT", {
365 cfb3116d Helga Velroyen
           "fields": [namefield] * 4,
366 cfb3116d Helga Velroyen
           }),
367 bab4f56a Helga Velroyen
368 cfb3116d Helga Velroyen
        ("/2/query/%s" % what, compat.partial(_Check, all_fields), "PUT", {
369 cfb3116d Helga Velroyen
           "fields": all_fields,
370 cfb3116d Helga Velroyen
           }),
371 4fab7cab Michael Hanselmann
372 cfb3116d Helga Velroyen
        ("/2/query/%s" % what, compat.partial(_Check, [namefield] * 4), "PUT", {
373 cfb3116d Helga Velroyen
           "fields": [namefield] * 4
374 bab4f56a Helga Velroyen
         })])
375 4fab7cab Michael Hanselmann
376 4fab7cab Michael Hanselmann
    def _CheckFilter():
377 4fab7cab Michael Hanselmann
      _DoTests([
378 4fab7cab Michael Hanselmann
        # With filter
379 4fab7cab Michael Hanselmann
        ("/2/query/%s" % what, compat.partial(_Check, all_fields), "PUT", {
380 4fab7cab Michael Hanselmann
           "fields": all_fields,
381 b5ae26cd Klaus Aehlig
           "filter": trivial_filter
382 4fab7cab Michael Hanselmann
           }),
383 4fab7cab Michael Hanselmann
        ])
384 4fab7cab Michael Hanselmann
385 4fab7cab Michael Hanselmann
    if what == constants.QR_LOCK:
386 4fab7cab Michael Hanselmann
      # Locks can't be filtered
387 4fab7cab Michael Hanselmann
      try:
388 4fab7cab Michael Hanselmann
        _CheckFilter()
389 4fab7cab Michael Hanselmann
      except rapi.client.GanetiApiError, err:
390 4fab7cab Michael Hanselmann
        AssertEqual(err.code, 500)
391 4fab7cab Michael Hanselmann
      else:
392 4fab7cab Michael Hanselmann
        raise qa_error.Error("Filtering locks didn't fail")
393 4fab7cab Michael Hanselmann
    else:
394 cfb3116d Helga Velroyen
      if what in constants.QR_VIA_RAPI_PUT:
395 cfb3116d Helga Velroyen
        _CheckFilter()
396 4fab7cab Michael Hanselmann
397 4fab7cab Michael Hanselmann
    if what == constants.QR_NODE:
398 4fab7cab Michael Hanselmann
      # Test with filter
399 5ae4945a Iustin Pop
      (nodes, ) = _DoTests(
400 5ae4945a Iustin Pop
        [("/2/query/%s" % what,
401 5ae4945a Iustin Pop
          compat.partial(_Check, ["name", "master"]), "PUT",
402 5ae4945a Iustin Pop
          {"fields": ["name", "master"],
403 5ae4945a Iustin Pop
           "filter": [qlang.OP_TRUE, "master"],
404 5ae4945a Iustin Pop
           })])
405 4fab7cab Michael Hanselmann
      qresult = objects.QueryResponse.FromDict(nodes)
406 4fab7cab Michael Hanselmann
      AssertEqual(qresult.data, [
407 4fab7cab Michael Hanselmann
        [[constants.RS_NORMAL, master_name], [constants.RS_NORMAL, True]],
408 4fab7cab Michael Hanselmann
        ])
409 4fab7cab Michael Hanselmann
410 4fab7cab Michael Hanselmann
411 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
412 a47f574c Oleksiy Mishchenko
def TestInstance(instance):
413 a47f574c Oleksiy Mishchenko
  """Testing getting instance(s) info via remote API.
414 a47f574c Oleksiy Mishchenko

415 a47f574c Oleksiy Mishchenko
  """
416 a47f574c Oleksiy Mishchenko
  def _VerifyInstance(data):
417 a47f574c Oleksiy Mishchenko
    for entry in INSTANCE_FIELDS:
418 a47f574c Oleksiy Mishchenko
      AssertIn(entry, data)
419 c85d3b64 Michael Hanselmann
420 a47f574c Oleksiy Mishchenko
  def _VerifyInstancesList(data):
421 a47f574c Oleksiy Mishchenko
    for instance in data:
422 c85d3b64 Michael Hanselmann
      for entry in LIST_FIELDS:
423 a47f574c Oleksiy Mishchenko
        AssertIn(entry, instance)
424 c85d3b64 Michael Hanselmann
425 a47f574c Oleksiy Mishchenko
  def _VerifyInstancesBulk(data):
426 a47f574c Oleksiy Mishchenko
    for instance_data in data:
427 a47f574c Oleksiy Mishchenko
      _VerifyInstance(instance_data)
428 a47f574c Oleksiy Mishchenko
429 a47f574c Oleksiy Mishchenko
  _DoTests([
430 b5f33afa Michael Hanselmann
    ("/2/instances/%s" % instance.name, _VerifyInstance, "GET", None),
431 d0c8c01d Iustin Pop
    ("/2/instances", _VerifyInstancesList, "GET", None),
432 d0c8c01d Iustin Pop
    ("/2/instances?bulk=1", _VerifyInstancesBulk, "GET", None),
433 b5f33afa Michael Hanselmann
    ("/2/instances/%s/activate-disks" % instance.name,
434 d0c8c01d Iustin Pop
     _VerifyReturnsJob, "PUT", None),
435 b5f33afa Michael Hanselmann
    ("/2/instances/%s/deactivate-disks" % instance.name,
436 d0c8c01d Iustin Pop
     _VerifyReturnsJob, "PUT", None),
437 a47f574c Oleksiy Mishchenko
    ])
438 a47f574c Oleksiy Mishchenko
439 71910715 Iustin Pop
  # Test OpBackupPrepare
440 ebeb600f Michael Hanselmann
  (job_id, ) = _DoTests([
441 ebeb600f Michael Hanselmann
    ("/2/instances/%s/prepare-export?mode=%s" %
442 b5f33afa Michael Hanselmann
     (instance.name, constants.EXPORT_MODE_REMOTE),
443 ebeb600f Michael Hanselmann
     _VerifyReturnsJob, "PUT", None),
444 ebeb600f Michael Hanselmann
    ])
445 ebeb600f Michael Hanselmann
446 ebeb600f Michael Hanselmann
  result = _WaitForRapiJob(job_id)[0]
447 ebeb600f Michael Hanselmann
  AssertEqual(len(result["handshake"]), 3)
448 ebeb600f Michael Hanselmann
  AssertEqual(result["handshake"][0], constants.RIE_VERSION)
449 ebeb600f Michael Hanselmann
  AssertEqual(len(result["x509_key_name"]), 3)
450 ebeb600f Michael Hanselmann
  AssertIn("-----BEGIN CERTIFICATE-----", result["x509_ca"])
451 ebeb600f Michael Hanselmann
452 a47f574c Oleksiy Mishchenko
453 a47f574c Oleksiy Mishchenko
def TestNode(node):
454 a47f574c Oleksiy Mishchenko
  """Testing getting node(s) info via remote API.
455 a47f574c Oleksiy Mishchenko

456 a47f574c Oleksiy Mishchenko
  """
457 a47f574c Oleksiy Mishchenko
  def _VerifyNode(data):
458 a47f574c Oleksiy Mishchenko
    for entry in NODE_FIELDS:
459 a47f574c Oleksiy Mishchenko
      AssertIn(entry, data)
460 c85d3b64 Michael Hanselmann
461 a47f574c Oleksiy Mishchenko
  def _VerifyNodesList(data):
462 a47f574c Oleksiy Mishchenko
    for node in data:
463 c85d3b64 Michael Hanselmann
      for entry in LIST_FIELDS:
464 a47f574c Oleksiy Mishchenko
        AssertIn(entry, node)
465 c85d3b64 Michael Hanselmann
466 a47f574c Oleksiy Mishchenko
  def _VerifyNodesBulk(data):
467 a47f574c Oleksiy Mishchenko
    for node_data in data:
468 a47f574c Oleksiy Mishchenko
      _VerifyNode(node_data)
469 a47f574c Oleksiy Mishchenko
470 a47f574c Oleksiy Mishchenko
  _DoTests([
471 aecba21e Michael Hanselmann
    ("/2/nodes/%s" % node.primary, _VerifyNode, "GET", None),
472 d0c8c01d Iustin Pop
    ("/2/nodes", _VerifyNodesList, "GET", None),
473 d0c8c01d Iustin Pop
    ("/2/nodes?bulk=1", _VerifyNodesBulk, "GET", None),
474 a47f574c Oleksiy Mishchenko
    ])
475 a47f574c Oleksiy Mishchenko
476 a47f574c Oleksiy Mishchenko
477 c1513c7f Michael Hanselmann
def _FilterTags(seq):
478 c1513c7f Michael Hanselmann
  """Removes unwanted tags from a sequence.
479 c1513c7f Michael Hanselmann

480 c1513c7f Michael Hanselmann
  """
481 c1513c7f Michael Hanselmann
  ignore_re = qa_config.get("ignore-tags-re", None)
482 c1513c7f Michael Hanselmann
483 c1513c7f Michael Hanselmann
  if ignore_re:
484 c1513c7f Michael Hanselmann
    return itertools.ifilterfalse(re.compile(ignore_re).match, seq)
485 c1513c7f Michael Hanselmann
  else:
486 c1513c7f Michael Hanselmann
    return seq
487 c1513c7f Michael Hanselmann
488 c1513c7f Michael Hanselmann
489 a47f574c Oleksiy Mishchenko
def TestTags(kind, name, tags):
490 a47f574c Oleksiy Mishchenko
  """Tests .../tags resources.
491 a47f574c Oleksiy Mishchenko

492 a47f574c Oleksiy Mishchenko
  """
493 a47f574c Oleksiy Mishchenko
  if kind == constants.TAG_CLUSTER:
494 a5b9d725 Iustin Pop
    uri = "/2/tags"
495 a47f574c Oleksiy Mishchenko
  elif kind == constants.TAG_NODE:
496 a5b9d725 Iustin Pop
    uri = "/2/nodes/%s/tags" % name
497 a47f574c Oleksiy Mishchenko
  elif kind == constants.TAG_INSTANCE:
498 a5b9d725 Iustin Pop
    uri = "/2/instances/%s/tags" % name
499 fe508a9d Michael Hanselmann
  elif kind == constants.TAG_NODEGROUP:
500 fe508a9d Michael Hanselmann
    uri = "/2/groups/%s/tags" % name
501 a47f574c Oleksiy Mishchenko
  else:
502 a47f574c Oleksiy Mishchenko
    raise errors.ProgrammerError("Unknown tag kind")
503 a47f574c Oleksiy Mishchenko
504 a47f574c Oleksiy Mishchenko
  def _VerifyTags(data):
505 c1513c7f Michael Hanselmann
    AssertEqual(sorted(tags), sorted(_FilterTags(data)))
506 a47f574c Oleksiy Mishchenko
507 4fab7cab Michael Hanselmann
  queryargs = "&".join("tag=%s" % i for i in tags)
508 c326b4ef Michael Hanselmann
509 c326b4ef Michael Hanselmann
  # Add tags
510 c326b4ef Michael Hanselmann
  (job_id, ) = _DoTests([
511 4fab7cab Michael Hanselmann
    ("%s?%s" % (uri, queryargs), _VerifyReturnsJob, "PUT", None),
512 c326b4ef Michael Hanselmann
    ])
513 c326b4ef Michael Hanselmann
  _WaitForRapiJob(job_id)
514 c326b4ef Michael Hanselmann
515 c326b4ef Michael Hanselmann
  # Retrieve tags
516 a47f574c Oleksiy Mishchenko
  _DoTests([
517 d0c8c01d Iustin Pop
    (uri, _VerifyTags, "GET", None),
518 a47f574c Oleksiy Mishchenko
    ])
519 8cb70e56 Michael Hanselmann
520 c326b4ef Michael Hanselmann
  # Remove tags
521 c326b4ef Michael Hanselmann
  (job_id, ) = _DoTests([
522 4fab7cab Michael Hanselmann
    ("%s?%s" % (uri, queryargs), _VerifyReturnsJob, "DELETE", None),
523 c326b4ef Michael Hanselmann
    ])
524 c326b4ef Michael Hanselmann
  _WaitForRapiJob(job_id)
525 c326b4ef Michael Hanselmann
526 8cb70e56 Michael Hanselmann
527 8cb70e56 Michael Hanselmann
def _WaitForRapiJob(job_id):
528 8cb70e56 Michael Hanselmann
  """Waits for a job to finish.
529 8cb70e56 Michael Hanselmann

530 8cb70e56 Michael Hanselmann
  """
531 8cb70e56 Michael Hanselmann
  def _VerifyJob(data):
532 8cb70e56 Michael Hanselmann
    AssertEqual(data["id"], job_id)
533 8cb70e56 Michael Hanselmann
    for field in JOB_FIELDS:
534 8cb70e56 Michael Hanselmann
      AssertIn(field, data)
535 8cb70e56 Michael Hanselmann
536 8cb70e56 Michael Hanselmann
  _DoTests([
537 8cb70e56 Michael Hanselmann
    ("/2/jobs/%s" % job_id, _VerifyJob, "GET", None),
538 8cb70e56 Michael Hanselmann
    ])
539 8cb70e56 Michael Hanselmann
540 ebeb600f Michael Hanselmann
  return rapi.client_utils.PollJob(_rapi_client, job_id,
541 ebeb600f Michael Hanselmann
                                   cli.StdioJobPollReportCb())
542 8cb70e56 Michael Hanselmann
543 8cb70e56 Michael Hanselmann
544 4b10fb65 Adeodato Simo
def TestRapiNodeGroups():
545 4b10fb65 Adeodato Simo
  """Test several node group operations using RAPI.
546 4b10fb65 Adeodato Simo

547 4b10fb65 Adeodato Simo
  """
548 b4d2d2cb Michael Hanselmann
  (group1, group2, group3) = qa_utils.GetNonexistentGroups(3)
549 4b10fb65 Adeodato Simo
550 4b10fb65 Adeodato Simo
  # Create a group with no attributes
551 4b10fb65 Adeodato Simo
  body = {
552 4b10fb65 Adeodato Simo
    "name": group1,
553 4b10fb65 Adeodato Simo
    }
554 4b10fb65 Adeodato Simo
555 4b10fb65 Adeodato Simo
  (job_id, ) = _DoTests([
556 4b10fb65 Adeodato Simo
    ("/2/groups", _VerifyReturnsJob, "POST", body),
557 4b10fb65 Adeodato Simo
    ])
558 4b10fb65 Adeodato Simo
559 4b10fb65 Adeodato Simo
  _WaitForRapiJob(job_id)
560 4b10fb65 Adeodato Simo
561 4b10fb65 Adeodato Simo
  # Create a group specifying alloc_policy
562 4b10fb65 Adeodato Simo
  body = {
563 4b10fb65 Adeodato Simo
    "name": group2,
564 4b10fb65 Adeodato Simo
    "alloc_policy": constants.ALLOC_POLICY_UNALLOCABLE,
565 4b10fb65 Adeodato Simo
    }
566 4b10fb65 Adeodato Simo
567 4b10fb65 Adeodato Simo
  (job_id, ) = _DoTests([
568 4b10fb65 Adeodato Simo
    ("/2/groups", _VerifyReturnsJob, "POST", body),
569 4b10fb65 Adeodato Simo
    ])
570 4b10fb65 Adeodato Simo
571 4b10fb65 Adeodato Simo
  _WaitForRapiJob(job_id)
572 4b10fb65 Adeodato Simo
573 4b10fb65 Adeodato Simo
  # Modify alloc_policy
574 4b10fb65 Adeodato Simo
  body = {
575 4b10fb65 Adeodato Simo
    "alloc_policy": constants.ALLOC_POLICY_UNALLOCABLE,
576 4b10fb65 Adeodato Simo
    }
577 4b10fb65 Adeodato Simo
578 4b10fb65 Adeodato Simo
  (job_id, ) = _DoTests([
579 4b10fb65 Adeodato Simo
    ("/2/groups/%s/modify" % group1, _VerifyReturnsJob, "PUT", body),
580 4b10fb65 Adeodato Simo
    ])
581 4b10fb65 Adeodato Simo
582 4b10fb65 Adeodato Simo
  _WaitForRapiJob(job_id)
583 4b10fb65 Adeodato Simo
584 4b10fb65 Adeodato Simo
  # Rename a group
585 4b10fb65 Adeodato Simo
  body = {
586 4b10fb65 Adeodato Simo
    "new_name": group3,
587 4b10fb65 Adeodato Simo
    }
588 4b10fb65 Adeodato Simo
589 4b10fb65 Adeodato Simo
  (job_id, ) = _DoTests([
590 4b10fb65 Adeodato Simo
    ("/2/groups/%s/rename" % group2, _VerifyReturnsJob, "PUT", body),
591 4b10fb65 Adeodato Simo
    ])
592 4b10fb65 Adeodato Simo
593 4b10fb65 Adeodato Simo
  _WaitForRapiJob(job_id)
594 4b10fb65 Adeodato Simo
595 4b10fb65 Adeodato Simo
  # Delete groups
596 4b10fb65 Adeodato Simo
  for group in [group1, group3]:
597 4b10fb65 Adeodato Simo
    (job_id, ) = _DoTests([
598 4b10fb65 Adeodato Simo
      ("/2/groups/%s" % group, _VerifyReturnsJob, "DELETE", None),
599 4b10fb65 Adeodato Simo
      ])
600 4b10fb65 Adeodato Simo
601 4b10fb65 Adeodato Simo
    _WaitForRapiJob(job_id)
602 4b10fb65 Adeodato Simo
603 4b10fb65 Adeodato Simo
604 924e95f9 Michael Hanselmann
def TestRapiInstanceAdd(node, use_client):
605 8cb70e56 Michael Hanselmann
  """Test adding a new instance via RAPI"""
606 bab4f56a Helga Velroyen
  if not qa_config.IsTemplateSupported(constants.DT_PLAIN):
607 bab4f56a Helga Velroyen
    return
608 8cb70e56 Michael Hanselmann
  instance = qa_config.AcquireInstance()
609 02a5fe0e Michael Hanselmann
  instance.SetDiskTemplate(constants.DT_PLAIN)
610 8cb70e56 Michael Hanselmann
  try:
611 090128b6 Christos Stavrakakis
    disks = [{"size": utils.ParseUnit(d.get("size")),
612 090128b6 Christos Stavrakakis
              "name": str(d.get("name"))}
613 090128b6 Christos Stavrakakis
             for d in qa_config.GetDiskOptions()]
614 0afce24e Michael Hanselmann
    nic0_mac = instance.GetNicMacAddr(0, constants.VALUE_GENERATE)
615 f346a7d9 Michael Hanselmann
    nics = [{
616 f346a7d9 Michael Hanselmann
      constants.INIC_MAC: nic0_mac,
617 f346a7d9 Michael Hanselmann
      }]
618 924e95f9 Michael Hanselmann
619 713a79e7 Michael Hanselmann
    beparams = {
620 8ccbbe4b Guido Trotter
      constants.BE_MAXMEM: utils.ParseUnit(qa_config.get(constants.BE_MAXMEM)),
621 8ccbbe4b Guido Trotter
      constants.BE_MINMEM: utils.ParseUnit(qa_config.get(constants.BE_MINMEM)),
622 713a79e7 Michael Hanselmann
      }
623 924e95f9 Michael Hanselmann
624 713a79e7 Michael Hanselmann
    if use_client:
625 924e95f9 Michael Hanselmann
      job_id = _rapi_client.CreateInstance(constants.INSTANCE_CREATE,
626 b5f33afa Michael Hanselmann
                                           instance.name,
627 924e95f9 Michael Hanselmann
                                           constants.DT_PLAIN,
628 924e95f9 Michael Hanselmann
                                           disks, nics,
629 924e95f9 Michael Hanselmann
                                           os=qa_config.get("os"),
630 aecba21e Michael Hanselmann
                                           pnode=node.primary,
631 924e95f9 Michael Hanselmann
                                           beparams=beparams)
632 924e95f9 Michael Hanselmann
    else:
633 924e95f9 Michael Hanselmann
      body = {
634 713a79e7 Michael Hanselmann
        "__version__": 1,
635 713a79e7 Michael Hanselmann
        "mode": constants.INSTANCE_CREATE,
636 b5f33afa Michael Hanselmann
        "name": instance.name,
637 713a79e7 Michael Hanselmann
        "os_type": qa_config.get("os"),
638 924e95f9 Michael Hanselmann
        "disk_template": constants.DT_PLAIN,
639 aecba21e Michael Hanselmann
        "pnode": node.primary,
640 713a79e7 Michael Hanselmann
        "beparams": beparams,
641 713a79e7 Michael Hanselmann
        "disks": disks,
642 713a79e7 Michael Hanselmann
        "nics": nics,
643 924e95f9 Michael Hanselmann
        }
644 924e95f9 Michael Hanselmann
645 924e95f9 Michael Hanselmann
      (job_id, ) = _DoTests([
646 924e95f9 Michael Hanselmann
        ("/2/instances", _VerifyReturnsJob, "POST", body),
647 924e95f9 Michael Hanselmann
        ])
648 8cb70e56 Michael Hanselmann
649 8cb70e56 Michael Hanselmann
    _WaitForRapiJob(job_id)
650 8cb70e56 Michael Hanselmann
651 8cb70e56 Michael Hanselmann
    return instance
652 8cb70e56 Michael Hanselmann
  except:
653 6f88e076 Michael Hanselmann
    instance.Release()
654 8cb70e56 Michael Hanselmann
    raise
655 8cb70e56 Michael Hanselmann
656 8cb70e56 Michael Hanselmann
657 5fa0375e Michael Hanselmann
@InstanceCheck(None, INST_DOWN, FIRST_ARG)
658 924e95f9 Michael Hanselmann
def TestRapiInstanceRemove(instance, use_client):
659 8cb70e56 Michael Hanselmann
  """Test removing instance via RAPI"""
660 bab4f56a Helga Velroyen
  # FIXME: this does not work if LVM is not enabled. Find out if this is a bug
661 bab4f56a Helga Velroyen
  # in RAPI or in the test
662 bab4f56a Helga Velroyen
  if not qa_config.IsStorageTypeSupported(constants.ST_LVM_VG):
663 bab4f56a Helga Velroyen
    return
664 bab4f56a Helga Velroyen
665 924e95f9 Michael Hanselmann
  if use_client:
666 b5f33afa Michael Hanselmann
    job_id = _rapi_client.DeleteInstance(instance.name)
667 924e95f9 Michael Hanselmann
  else:
668 924e95f9 Michael Hanselmann
    (job_id, ) = _DoTests([
669 b5f33afa Michael Hanselmann
      ("/2/instances/%s" % instance.name, _VerifyReturnsJob, "DELETE", None),
670 924e95f9 Michael Hanselmann
      ])
671 8cb70e56 Michael Hanselmann
672 8cb70e56 Michael Hanselmann
  _WaitForRapiJob(job_id)
673 8cb70e56 Michael Hanselmann
674 5d831182 Michael Hanselmann
675 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
676 938bde86 Michael Hanselmann
def TestRapiInstanceMigrate(instance):
677 938bde86 Michael Hanselmann
  """Test migrating instance via RAPI"""
678 5de31440 Bernardo Dal Seno
  if not IsMigrationSupported(instance):
679 5de31440 Bernardo Dal Seno
    print qa_utils.FormatInfo("Instance doesn't support migration, skipping"
680 5de31440 Bernardo Dal Seno
                              " test")
681 5de31440 Bernardo Dal Seno
    return
682 938bde86 Michael Hanselmann
  # Move to secondary node
683 b5f33afa Michael Hanselmann
  _WaitForRapiJob(_rapi_client.MigrateInstance(instance.name))
684 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, True)
685 938bde86 Michael Hanselmann
  # And back to previous primary
686 b5f33afa Michael Hanselmann
  _WaitForRapiJob(_rapi_client.MigrateInstance(instance.name))
687 c0a146a1 Michael Hanselmann
688 c0a146a1 Michael Hanselmann
689 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
690 c0a146a1 Michael Hanselmann
def TestRapiInstanceFailover(instance):
691 c0a146a1 Michael Hanselmann
  """Test failing over instance via RAPI"""
692 5de31440 Bernardo Dal Seno
  if not IsFailoverSupported(instance):
693 5de31440 Bernardo Dal Seno
    print qa_utils.FormatInfo("Instance doesn't support failover, skipping"
694 5de31440 Bernardo Dal Seno
                              " test")
695 5de31440 Bernardo Dal Seno
    return
696 c0a146a1 Michael Hanselmann
  # Move to secondary node
697 b5f33afa Michael Hanselmann
  _WaitForRapiJob(_rapi_client.FailoverInstance(instance.name))
698 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, True)
699 c0a146a1 Michael Hanselmann
  # And back to previous primary
700 b5f33afa Michael Hanselmann
  _WaitForRapiJob(_rapi_client.FailoverInstance(instance.name))
701 a7418448 Michael Hanselmann
702 a7418448 Michael Hanselmann
703 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_DOWN, FIRST_ARG)
704 a7418448 Michael Hanselmann
def TestRapiInstanceShutdown(instance):
705 a7418448 Michael Hanselmann
  """Test stopping an instance via RAPI"""
706 b5f33afa Michael Hanselmann
  _WaitForRapiJob(_rapi_client.ShutdownInstance(instance.name))
707 a7418448 Michael Hanselmann
708 a7418448 Michael Hanselmann
709 5fa0375e Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_UP, FIRST_ARG)
710 a7418448 Michael Hanselmann
def TestRapiInstanceStartup(instance):
711 a7418448 Michael Hanselmann
  """Test starting an instance via RAPI"""
712 b5f33afa Michael Hanselmann
  _WaitForRapiJob(_rapi_client.StartupInstance(instance.name))
713 938bde86 Michael Hanselmann
714 938bde86 Michael Hanselmann
715 51131cad Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
716 4c1a464b Iustin Pop
def TestRapiInstanceRenameAndBack(rename_source, rename_target):
717 4c1a464b Iustin Pop
  """Test renaming instance via RAPI
718 4c1a464b Iustin Pop

719 4c1a464b Iustin Pop
  This must leave the instance with the original name (in the
720 4c1a464b Iustin Pop
  non-failure case).
721 4c1a464b Iustin Pop

722 4c1a464b Iustin Pop
  """
723 e5c2accd Guido Trotter
  _WaitForRapiJob(_rapi_client.RenameInstance(rename_source, rename_target))
724 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(rename_source, False)
725 51131cad Michael Hanselmann
  qa_utils.RunInstanceCheck(rename_target, False)
726 4c1a464b Iustin Pop
  _WaitForRapiJob(_rapi_client.RenameInstance(rename_target, rename_source))
727 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(rename_target, False)
728 7fb50870 Michael Hanselmann
729 7fb50870 Michael Hanselmann
730 5fa0375e Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
731 0220d2cf Guido Trotter
def TestRapiInstanceReinstall(instance):
732 0220d2cf Guido Trotter
  """Test reinstalling an instance via RAPI"""
733 ad658827 Bernardo Dal Seno
  if instance.disk_template == constants.DT_DISKLESS:
734 ad658827 Bernardo Dal Seno
    print qa_utils.FormatInfo("Test not supported for diskless instances")
735 ad658827 Bernardo Dal Seno
    return
736 ad658827 Bernardo Dal Seno
737 b5f33afa Michael Hanselmann
  _WaitForRapiJob(_rapi_client.ReinstallInstance(instance.name))
738 51131cad Michael Hanselmann
  # By default, the instance is started again
739 51131cad Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, True)
740 51131cad Michael Hanselmann
741 51131cad Michael Hanselmann
  # Reinstall again without starting
742 b5f33afa Michael Hanselmann
  _WaitForRapiJob(_rapi_client.ReinstallInstance(instance.name,
743 51131cad Michael Hanselmann
                                                 no_startup=True))
744 0220d2cf Guido Trotter
745 0220d2cf Guido Trotter
746 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
747 539d65ba Michael Hanselmann
def TestRapiInstanceReplaceDisks(instance):
748 539d65ba Michael Hanselmann
  """Test replacing instance disks via RAPI"""
749 5de31440 Bernardo Dal Seno
  if not IsDiskReplacingSupported(instance):
750 5de31440 Bernardo Dal Seno
    print qa_utils.FormatInfo("Instance doesn't support disk replacing,"
751 5de31440 Bernardo Dal Seno
                              " skipping test")
752 5de31440 Bernardo Dal Seno
    return
753 5ae4945a Iustin Pop
  fn = _rapi_client.ReplaceInstanceDisks
754 b5f33afa Michael Hanselmann
  _WaitForRapiJob(fn(instance.name,
755 5ae4945a Iustin Pop
                     mode=constants.REPLACE_DISK_AUTO, disks=[]))
756 b5f33afa Michael Hanselmann
  _WaitForRapiJob(fn(instance.name,
757 5ae4945a Iustin Pop
                     mode=constants.REPLACE_DISK_SEC, disks="0"))
758 539d65ba Michael Hanselmann
759 539d65ba Michael Hanselmann
760 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
761 3b7158ef Michael Hanselmann
def TestRapiInstanceModify(instance):
762 3b7158ef Michael Hanselmann
  """Test modifying instance via RAPI"""
763 a8dbf746 Michael Hanselmann
  default_hv = qa_config.GetDefaultHypervisor()
764 a8dbf746 Michael Hanselmann
765 3b7158ef Michael Hanselmann
  def _ModifyInstance(**kwargs):
766 b5f33afa Michael Hanselmann
    _WaitForRapiJob(_rapi_client.ModifyInstance(instance.name, **kwargs))
767 3b7158ef Michael Hanselmann
768 3b7158ef Michael Hanselmann
  _ModifyInstance(beparams={
769 3b7158ef Michael Hanselmann
    constants.BE_VCPUS: 3,
770 3b7158ef Michael Hanselmann
    })
771 3b7158ef Michael Hanselmann
772 3b7158ef Michael Hanselmann
  _ModifyInstance(beparams={
773 3b7158ef Michael Hanselmann
    constants.BE_VCPUS: constants.VALUE_DEFAULT,
774 3b7158ef Michael Hanselmann
    })
775 3b7158ef Michael Hanselmann
776 a8dbf746 Michael Hanselmann
  if default_hv == constants.HT_XEN_PVM:
777 a8dbf746 Michael Hanselmann
    _ModifyInstance(hvparams={
778 a8dbf746 Michael Hanselmann
      constants.HV_KERNEL_ARGS: "single",
779 a8dbf746 Michael Hanselmann
      })
780 a8dbf746 Michael Hanselmann
    _ModifyInstance(hvparams={
781 a8dbf746 Michael Hanselmann
      constants.HV_KERNEL_ARGS: constants.VALUE_DEFAULT,
782 a8dbf746 Michael Hanselmann
      })
783 a8dbf746 Michael Hanselmann
  elif default_hv == constants.HT_XEN_HVM:
784 a8dbf746 Michael Hanselmann
    _ModifyInstance(hvparams={
785 a8dbf746 Michael Hanselmann
      constants.HV_BOOT_ORDER: "acn",
786 a8dbf746 Michael Hanselmann
      })
787 a8dbf746 Michael Hanselmann
    _ModifyInstance(hvparams={
788 a8dbf746 Michael Hanselmann
      constants.HV_BOOT_ORDER: constants.VALUE_DEFAULT,
789 a8dbf746 Michael Hanselmann
      })
790 3b7158ef Michael Hanselmann
791 3b7158ef Michael Hanselmann
792 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
793 b82d4c5e Michael Hanselmann
def TestRapiInstanceConsole(instance):
794 b82d4c5e Michael Hanselmann
  """Test getting instance console information via RAPI"""
795 b5f33afa Michael Hanselmann
  result = _rapi_client.GetInstanceConsole(instance.name)
796 b82d4c5e Michael Hanselmann
  console = objects.InstanceConsole.FromDict(result)
797 b82d4c5e Michael Hanselmann
  AssertEqual(console.Validate(), True)
798 b5f33afa Michael Hanselmann
  AssertEqual(console.instance, qa_utils.ResolveInstanceName(instance.name))
799 b82d4c5e Michael Hanselmann
800 b82d4c5e Michael Hanselmann
801 5fa0375e Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
802 b82d4c5e Michael Hanselmann
def TestRapiStoppedInstanceConsole(instance):
803 b82d4c5e Michael Hanselmann
  """Test getting stopped instance's console information via RAPI"""
804 b82d4c5e Michael Hanselmann
  try:
805 b5f33afa Michael Hanselmann
    _rapi_client.GetInstanceConsole(instance.name)
806 b82d4c5e Michael Hanselmann
  except rapi.client.GanetiApiError, err:
807 b82d4c5e Michael Hanselmann
    AssertEqual(err.code, 503)
808 b82d4c5e Michael Hanselmann
  else:
809 b82d4c5e Michael Hanselmann
    raise qa_error.Error("Getting console for stopped instance didn't"
810 b82d4c5e Michael Hanselmann
                         " return HTTP 503")
811 b82d4c5e Michael Hanselmann
812 b82d4c5e Michael Hanselmann
813 2932dc44 Michael Hanselmann
def GetOperatingSystems():
814 2932dc44 Michael Hanselmann
  """Retrieves a list of all available operating systems.
815 2932dc44 Michael Hanselmann

816 2932dc44 Michael Hanselmann
  """
817 2932dc44 Michael Hanselmann
  return _rapi_client.GetOperatingSystems()
818 2932dc44 Michael Hanselmann
819 2932dc44 Michael Hanselmann
820 638a7266 Iustin Pop
def TestInterClusterInstanceMove(src_instance, dest_instance,
821 66743fe3 Hrvoje Ribicic
                                 inodes, tnode, perform_checks=True):
822 5d831182 Michael Hanselmann
  """Test tools/move-instance"""
823 5d831182 Michael Hanselmann
  master = qa_config.GetMasterNode()
824 5d831182 Michael Hanselmann
825 5d831182 Michael Hanselmann
  rapi_pw_file = tempfile.NamedTemporaryFile()
826 5d831182 Michael Hanselmann
  rapi_pw_file.write(_rapi_password)
827 5d831182 Michael Hanselmann
  rapi_pw_file.flush()
828 5d831182 Michael Hanselmann
829 66743fe3 Hrvoje Ribicic
  # Needed only if checks are to be performed
830 66743fe3 Hrvoje Ribicic
  if perform_checks:
831 66743fe3 Hrvoje Ribicic
    dest_instance.SetDiskTemplate(src_instance.disk_template)
832 906a0346 Bernardo Dal Seno
833 5d831182 Michael Hanselmann
  # TODO: Run some instance tests before moving back
834 677e16eb Iustin Pop
835 c99200a3 Bernardo Dal Seno
  if len(inodes) > 1:
836 c99200a3 Bernardo Dal Seno
    # No disk template currently requires more than 1 secondary node. If this
837 c99200a3 Bernardo Dal Seno
    # changes, either this test must be skipped or the script must be updated.
838 c99200a3 Bernardo Dal Seno
    assert len(inodes) == 2
839 c99200a3 Bernardo Dal Seno
    snode = inodes[1]
840 c99200a3 Bernardo Dal Seno
  else:
841 638a7266 Iustin Pop
    # instance is not redundant, but we still need to pass a node
842 638a7266 Iustin Pop
    # (which will be ignored)
843 c99200a3 Bernardo Dal Seno
    snode = tnode
844 c99200a3 Bernardo Dal Seno
  pnode = inodes[0]
845 638a7266 Iustin Pop
  # note: pnode:snode are the *current* nodes, so we move it first to
846 638a7266 Iustin Pop
  # tnode:pnode, then back to pnode:snode
847 66743fe3 Hrvoje Ribicic
  for current_src_inst, current_dest_inst, target_pnode, target_snode in \
848 66743fe3 Hrvoje Ribicic
    [(src_instance.name, dest_instance.name, tnode.primary, pnode.primary),
849 66743fe3 Hrvoje Ribicic
     (dest_instance.name, src_instance.name, pnode.primary, snode.primary)]:
850 5d831182 Michael Hanselmann
    cmd = [
851 5d831182 Michael Hanselmann
      "../tools/move-instance",
852 5d831182 Michael Hanselmann
      "--verbose",
853 5d831182 Michael Hanselmann
      "--src-ca-file=%s" % _rapi_ca.name,
854 5d831182 Michael Hanselmann
      "--src-username=%s" % _rapi_username,
855 5d831182 Michael Hanselmann
      "--src-password-file=%s" % rapi_pw_file.name,
856 66743fe3 Hrvoje Ribicic
      "--dest-instance-name=%s" % current_dest_inst,
857 66743fe3 Hrvoje Ribicic
      "--dest-primary-node=%s" % target_pnode,
858 66743fe3 Hrvoje Ribicic
      "--dest-secondary-node=%s" % target_snode,
859 a889c536 Michael Hanselmann
      "--net=0:mac=%s" % constants.VALUE_GENERATE,
860 aecba21e Michael Hanselmann
      master.primary,
861 aecba21e Michael Hanselmann
      master.primary,
862 66743fe3 Hrvoje Ribicic
      current_src_inst,
863 5d831182 Michael Hanselmann
      ]
864 5d831182 Michael Hanselmann
865 66743fe3 Hrvoje Ribicic
    # Some uses of this test might require that RAPI-only commands are used,
866 66743fe3 Hrvoje Ribicic
    # and the checks are command-line based.
867 66743fe3 Hrvoje Ribicic
868 66743fe3 Hrvoje Ribicic
    if perform_checks:
869 66743fe3 Hrvoje Ribicic
      qa_utils.RunInstanceCheck(current_dest_inst, False)
870 66743fe3 Hrvoje Ribicic
871 5d831182 Michael Hanselmann
    AssertEqual(StartLocalCommand(cmd).wait(), 0)
872 66743fe3 Hrvoje Ribicic
873 66743fe3 Hrvoje Ribicic
    if perform_checks:
874 66743fe3 Hrvoje Ribicic
      qa_utils.RunInstanceCheck(current_src_inst, False)
875 66743fe3 Hrvoje Ribicic
      qa_utils.RunInstanceCheck(current_dest_inst, True)