Statistics
| Branch: | Tag: | Revision:

root / qa / qa_rapi.py @ ebeb600f

History | View | Annotate | Download (8.6 kB)

1
#
2

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

    
20

    
21
"""Remote API QA tests.
22

23
"""
24

    
25
import tempfile
26

    
27
from ganeti import utils
28
from ganeti import constants
29
from ganeti import errors
30
from ganeti import serializer
31
from ganeti import cli
32
from ganeti import rapi
33

    
34
import ganeti.rapi.client
35
import ganeti.rapi.client_utils
36

    
37
import qa_config
38
import qa_utils
39
import qa_error
40

    
41
from qa_utils import (AssertEqual, AssertNotEqual, AssertIn, AssertMatch,
42
                      StartSSH)
43

    
44

    
45
_rapi_ca = None
46
_rapi_client = None
47

    
48

    
49
def Setup(username, password):
50
  """Configures the RAPI client.
51

52
  """
53
  global _rapi_ca
54
  global _rapi_client
55

    
56
  master = qa_config.GetMasterNode()
57

    
58
  # Load RAPI certificate from master node
59
  cmd = ["cat", constants.RAPI_CERT_FILE]
60

    
61
  # Write to temporary file
62
  _rapi_ca = tempfile.NamedTemporaryFile()
63
  _rapi_ca.write(qa_utils.GetCommandOutput(master["primary"],
64
                                           utils.ShellQuoteArgs(cmd)))
65
  _rapi_ca.flush()
66

    
67
  port = qa_config.get("rapi-port", default=constants.DEFAULT_RAPI_PORT)
68
  cfg_ssl = rapi.client.CertAuthorityVerify(cafile=_rapi_ca.name)
69

    
70
  _rapi_client = rapi.client.GanetiRapiClient(master["primary"], port=port,
71
                                              username=username,
72
                                              password=password,
73
                                              config_ssl_verification=cfg_ssl,
74
                                              ignore_proxy=True)
75

    
76
  print "RAPI protocol version: %s" % _rapi_client.GetVersion()
77

    
78

    
79
INSTANCE_FIELDS = ("name", "os", "pnode", "snodes",
80
                   "admin_state",
81
                   "disk_template", "disk.sizes",
82
                   "nic.ips", "nic.macs", "nic.modes", "nic.links",
83
                   "beparams", "hvparams",
84
                   "oper_state", "oper_ram", "status", "tags")
85

    
86
NODE_FIELDS = ("name", "dtotal", "dfree",
87
               "mtotal", "mnode", "mfree",
88
               "pinst_cnt", "sinst_cnt", "tags")
89

    
90
JOB_FIELDS = frozenset([
91
  "id", "ops", "status", "summary",
92
  "opstatus", "opresult", "oplog",
93
  "received_ts", "start_ts", "end_ts",
94
  ])
95

    
96
LIST_FIELDS = ("id", "uri")
97

    
98

    
99
def Enabled():
100
  """Return whether remote API tests should be run.
101

102
  """
103
  return qa_config.TestEnabled('rapi')
104

    
105

    
106
def _DoTests(uris):
107
  results = []
108

    
109
  for uri, verify, method, body in uris:
110
    assert uri.startswith("/")
111

    
112
    data = _rapi_client._SendRequest(method, uri, None, body)
113

    
114
    if verify is not None:
115
      if callable(verify):
116
        verify(data)
117
      else:
118
        AssertEqual(data, verify)
119

    
120
      results.append(data)
121

    
122
  return results
123

    
124

    
125
def _VerifyReturnsJob(data):
126
  AssertMatch(data, r'^\d+$')
127

    
128

    
129
def TestVersion():
130
  """Testing remote API version.
131

132
  """
133
  _DoTests([
134
    ("/version", constants.RAPI_VERSION, 'GET', None),
135
    ])
136

    
137

    
138
def TestEmptyCluster():
139
  """Testing remote API on an empty cluster.
140

141
  """
142
  master = qa_config.GetMasterNode()
143
  master_full = qa_utils.ResolveNodeName(master)
144

    
145
  def _VerifyInfo(data):
146
    AssertIn("name", data)
147
    AssertIn("master", data)
148
    AssertEqual(data["master"], master_full)
149

    
150
  def _VerifyNodes(data):
151
    master_entry = {
152
      "id": master_full,
153
      "uri": "/2/nodes/%s" % master_full,
154
      }
155
    AssertIn(master_entry, data)
156

    
157
  def _VerifyNodesBulk(data):
158
    for node in data:
159
      for entry in NODE_FIELDS:
160
        AssertIn(entry, node)
161

    
162
  _DoTests([
163
    ("/", None, 'GET', None),
164
    ("/2/info", _VerifyInfo, 'GET', None),
165
    ("/2/tags", None, 'GET', None),
166
    ("/2/nodes", _VerifyNodes, 'GET', None),
167
    ("/2/nodes?bulk=1", _VerifyNodesBulk, 'GET', None),
168
    ("/2/instances", [], 'GET', None),
169
    ("/2/instances?bulk=1", [], 'GET', None),
170
    ("/2/os", None, 'GET', None),
171
    ])
172

    
173

    
174
def TestInstance(instance):
175
  """Testing getting instance(s) info via remote API.
176

177
  """
178
  def _VerifyInstance(data):
179
    for entry in INSTANCE_FIELDS:
180
      AssertIn(entry, data)
181

    
182
  def _VerifyInstancesList(data):
183
    for instance in data:
184
      for entry in LIST_FIELDS:
185
        AssertIn(entry, instance)
186

    
187
  def _VerifyInstancesBulk(data):
188
    for instance_data in data:
189
      _VerifyInstance(instance_data)
190

    
191
  _DoTests([
192
    ("/2/instances/%s" % instance["name"], _VerifyInstance, 'GET', None),
193
    ("/2/instances", _VerifyInstancesList, 'GET', None),
194
    ("/2/instances?bulk=1", _VerifyInstancesBulk, 'GET', None),
195
    ("/2/instances/%s/activate-disks" % instance["name"],
196
     _VerifyReturnsJob, 'PUT', None),
197
    ("/2/instances/%s/deactivate-disks" % instance["name"],
198
     _VerifyReturnsJob, 'PUT', None),
199
    ])
200

    
201
  # Test OpPrepareExport
202
  (job_id, ) = _DoTests([
203
    ("/2/instances/%s/prepare-export?mode=%s" %
204
     (instance["name"], constants.EXPORT_MODE_REMOTE),
205
     _VerifyReturnsJob, "PUT", None),
206
    ])
207

    
208
  result = _WaitForRapiJob(job_id)[0]
209
  AssertEqual(len(result["handshake"]), 3)
210
  AssertEqual(result["handshake"][0], constants.RIE_VERSION)
211
  AssertEqual(len(result["x509_key_name"]), 3)
212
  AssertIn("-----BEGIN CERTIFICATE-----", result["x509_ca"])
213

    
214

    
215
def TestNode(node):
216
  """Testing getting node(s) info via remote API.
217

218
  """
219
  def _VerifyNode(data):
220
    for entry in NODE_FIELDS:
221
      AssertIn(entry, data)
222

    
223
  def _VerifyNodesList(data):
224
    for node in data:
225
      for entry in LIST_FIELDS:
226
        AssertIn(entry, node)
227

    
228
  def _VerifyNodesBulk(data):
229
    for node_data in data:
230
      _VerifyNode(node_data)
231

    
232
  _DoTests([
233
    ("/2/nodes/%s" % node["primary"], _VerifyNode, 'GET', None),
234
    ("/2/nodes", _VerifyNodesList, 'GET', None),
235
    ("/2/nodes?bulk=1", _VerifyNodesBulk, 'GET', None),
236
    ])
237

    
238

    
239
def TestTags(kind, name, tags):
240
  """Tests .../tags resources.
241

242
  """
243
  if kind == constants.TAG_CLUSTER:
244
    uri = "/2/tags"
245
  elif kind == constants.TAG_NODE:
246
    uri = "/2/nodes/%s/tags" % name
247
  elif kind == constants.TAG_INSTANCE:
248
    uri = "/2/instances/%s/tags" % name
249
  else:
250
    raise errors.ProgrammerError("Unknown tag kind")
251

    
252
  def _VerifyTags(data):
253
    AssertEqual(sorted(tags), sorted(data))
254

    
255
  _DoTests([
256
    (uri, _VerifyTags, 'GET', None),
257
    ])
258

    
259

    
260
def _WaitForRapiJob(job_id):
261
  """Waits for a job to finish.
262

263
  """
264
  master = qa_config.GetMasterNode()
265

    
266
  def _VerifyJob(data):
267
    AssertEqual(data["id"], job_id)
268
    for field in JOB_FIELDS:
269
      AssertIn(field, data)
270

    
271
  _DoTests([
272
    ("/2/jobs/%s" % job_id, _VerifyJob, "GET", None),
273
    ])
274

    
275
  return rapi.client_utils.PollJob(_rapi_client, job_id,
276
                                   cli.StdioJobPollReportCb())
277

    
278

    
279
def TestRapiInstanceAdd(node, use_client):
280
  """Test adding a new instance via RAPI"""
281
  instance = qa_config.AcquireInstance()
282
  try:
283
    memory = utils.ParseUnit(qa_config.get("mem"))
284
    disk_sizes = [utils.ParseUnit(size) for size in qa_config.get("disk")]
285

    
286
    if use_client:
287
      disks = [{"size": size} for size in disk_sizes]
288
      nics = [{}]
289

    
290
      beparams = {
291
        constants.BE_MEMORY: memory,
292
        }
293

    
294
      job_id = _rapi_client.CreateInstance(constants.INSTANCE_CREATE,
295
                                           instance["name"],
296
                                           constants.DT_PLAIN,
297
                                           disks, nics,
298
                                           os=qa_config.get("os"),
299
                                           pnode=node["primary"],
300
                                           beparams=beparams)
301
    else:
302
      body = {
303
        "name": instance["name"],
304
        "os": qa_config.get("os"),
305
        "disk_template": constants.DT_PLAIN,
306
        "pnode": node["primary"],
307
        "memory": memory,
308
        "disks": disk_sizes,
309
        }
310

    
311
      (job_id, ) = _DoTests([
312
        ("/2/instances", _VerifyReturnsJob, "POST", body),
313
        ])
314

    
315
    _WaitForRapiJob(job_id)
316

    
317
    return instance
318
  except:
319
    qa_config.ReleaseInstance(instance)
320
    raise
321

    
322

    
323
def TestRapiInstanceRemove(instance, use_client):
324
  """Test removing instance via RAPI"""
325
  if use_client:
326
    job_id = _rapi_client.DeleteInstance(instance["name"])
327
  else:
328
    (job_id, ) = _DoTests([
329
      ("/2/instances/%s" % instance["name"], _VerifyReturnsJob, "DELETE", None),
330
      ])
331

    
332
  _WaitForRapiJob(job_id)
333

    
334
  qa_config.ReleaseInstance(instance)