Statistics
| Branch: | Tag: | Revision:

root / qa / qa_rapi.py @ 924e95f9

History | View | Annotate | Download (8.1 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

    
202
def TestNode(node):
203
  """Testing getting node(s) info via remote API.
204

205
  """
206
  def _VerifyNode(data):
207
    for entry in NODE_FIELDS:
208
      AssertIn(entry, data)
209

    
210
  def _VerifyNodesList(data):
211
    for node in data:
212
      for entry in LIST_FIELDS:
213
        AssertIn(entry, node)
214

    
215
  def _VerifyNodesBulk(data):
216
    for node_data in data:
217
      _VerifyNode(node_data)
218

    
219
  _DoTests([
220
    ("/2/nodes/%s" % node["primary"], _VerifyNode, 'GET', None),
221
    ("/2/nodes", _VerifyNodesList, 'GET', None),
222
    ("/2/nodes?bulk=1", _VerifyNodesBulk, 'GET', None),
223
    ])
224

    
225

    
226
def TestTags(kind, name, tags):
227
  """Tests .../tags resources.
228

229
  """
230
  if kind == constants.TAG_CLUSTER:
231
    uri = "/2/tags"
232
  elif kind == constants.TAG_NODE:
233
    uri = "/2/nodes/%s/tags" % name
234
  elif kind == constants.TAG_INSTANCE:
235
    uri = "/2/instances/%s/tags" % name
236
  else:
237
    raise errors.ProgrammerError("Unknown tag kind")
238

    
239
  def _VerifyTags(data):
240
    AssertEqual(sorted(tags), sorted(data))
241

    
242
  _DoTests([
243
    (uri, _VerifyTags, 'GET', None),
244
    ])
245

    
246

    
247
def _WaitForRapiJob(job_id):
248
  """Waits for a job to finish.
249

250
  """
251
  master = qa_config.GetMasterNode()
252

    
253
  def _VerifyJob(data):
254
    AssertEqual(data["id"], job_id)
255
    for field in JOB_FIELDS:
256
      AssertIn(field, data)
257

    
258
  _DoTests([
259
    ("/2/jobs/%s" % job_id, _VerifyJob, "GET", None),
260
    ])
261

    
262
  rapi.client_utils.PollJob(_rapi_client, job_id, cli.StdioJobPollReportCb())
263

    
264

    
265
def TestRapiInstanceAdd(node, use_client):
266
  """Test adding a new instance via RAPI"""
267
  instance = qa_config.AcquireInstance()
268
  try:
269
    memory = utils.ParseUnit(qa_config.get("mem"))
270
    disk_sizes = [utils.ParseUnit(size) for size in qa_config.get("disk")]
271

    
272
    if use_client:
273
      disks = [{"size": size} for size in disk_sizes]
274
      nics = [{}]
275

    
276
      beparams = {
277
        constants.BE_MEMORY: memory,
278
        }
279

    
280
      job_id = _rapi_client.CreateInstance(constants.INSTANCE_CREATE,
281
                                           instance["name"],
282
                                           constants.DT_PLAIN,
283
                                           disks, nics,
284
                                           os=qa_config.get("os"),
285
                                           pnode=node["primary"],
286
                                           beparams=beparams)
287
    else:
288
      body = {
289
        "name": instance["name"],
290
        "os": qa_config.get("os"),
291
        "disk_template": constants.DT_PLAIN,
292
        "pnode": node["primary"],
293
        "memory": memory,
294
        "disks": disk_sizes,
295
        }
296

    
297
      (job_id, ) = _DoTests([
298
        ("/2/instances", _VerifyReturnsJob, "POST", body),
299
        ])
300

    
301
    _WaitForRapiJob(job_id)
302

    
303
    return instance
304
  except:
305
    qa_config.ReleaseInstance(instance)
306
    raise
307

    
308

    
309
def TestRapiInstanceRemove(instance, use_client):
310
  """Test removing instance via RAPI"""
311
  if use_client:
312
    job_id = _rapi_client.DeleteInstance(instance["name"])
313
  else:
314
    (job_id, ) = _DoTests([
315
      ("/2/instances/%s" % instance["name"], _VerifyReturnsJob, "DELETE", None),
316
      ])
317

    
318
  _WaitForRapiJob(job_id)
319

    
320
  qa_config.ReleaseInstance(instance)