Revision a47f574c

b/Makefile.am
157 157
	qa/qa_node.py \
158 158
	qa/qa_os.py \
159 159
	qa/qa_other.py \
160
	qa/qa_rapi.py \
160 161
	qa/qa_tags.py \
161 162
	qa/qa_utils.py
162 163

  
b/qa/ganeti-qa.py
39 39
import qa_node
40 40
import qa_os
41 41
import qa_other
42
import qa_rapi
42 43
import qa_tags
43 44
import qa_utils
44 45

  
......
111 112
  if qa_config.TestEnabled('cluster-master-failover'):
112 113
    RunTest(qa_cluster.TestClusterMasterFailover)
113 114

  
115
  if qa_rapi.Enabled():
116
    RunTest(qa_rapi.TestVersion)
117
    RunTest(qa_rapi.TestEmptyCluster)
114 118

  
115 119
def RunOsTests():
116 120
  """Runs all tests related to gnt-os.
......
160 164
  if qa_config.TestEnabled('node-volumes'):
161 165
    RunTest(qa_node.TestNodeVolumes)
162 166

  
167
  if qa_rapi.Enabled():
168
    RunTest(qa_rapi.TestInstance, instance)
163 169

  
164 170
def RunExportImportTests(instance, pnode):
165 171
  """Tries to export and import the instance.
......
282 288
    if qa_config.TestEnabled('tags'):
283 289
      RunTest(qa_tags.TestNodeTags, pnode)
284 290

  
291
    if qa_rapi.Enabled():
292
      RunTest(qa_rapi.TestNode, pnode)
293

  
285 294
    if qa_config.TestEnabled('instance-add-plain-disk'):
286 295
      instance = RunTest(qa_instance.TestInstanceAddWithPlainDisk, pnode)
287 296
      RunCommonInstanceTests(instance)
b/qa/qa-sample.yaml
29 29
  env: True
30 30
  os: True
31 31
  tags: True
32
  rapi: True
32 33

  
33 34
  cluster-verify: True
34 35
  cluster-info: True
b/qa/qa_rapi.py
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 urllib2
26

  
27
from ganeti import utils
28
from ganeti import constants
29
from ganeti import errors
30
from ganeti import serializer
31

  
32
import qa_config
33
import qa_utils
34
import qa_error
35

  
36
from qa_utils import AssertEqual, AssertNotEqual, AssertIn, StartSSH
37

  
38

  
39
# Create opener which doesn't try to look for proxies.
40
NoProxyOpener = urllib2.build_opener(urllib2.ProxyHandler({}))
41

  
42

  
43
INSTANCE_FIELDS = ("name", "os", "pnode", "snodes",
44
                   "admin_state", "admin_ram",
45
                   "disk_template", "ip", "mac", "bridge",
46
                   "sda_size", "sdb_size", "vcpus",
47
                   "oper_state", "status", "tags")
48

  
49
NODE_FIELDS = ("name", "dtotal", "dfree",
50
               "mtotal", "mnode", "mfree",
51
               "pinst_cnt", "sinst_cnt", "tags")
52

  
53
LIST_FIELDS = ("name", "uri")
54

  
55

  
56
def Enabled():
57
  """Return whether remote API tests should be run.
58

  
59
  """
60
  return constants.RAPI_ENABLE and qa_config.TestEnabled('rapi')
61

  
62

  
63
def PrintRemoteAPIWarning():
64
  """Print warning if remote API is not enabled.
65

  
66
  """
67
  if constants.RAPI_ENABLE or not qa_config.TestEnabled('rapi'):
68
    return
69
  msg = ("Remote API is not enabled in this Ganeti build. Please run"
70
         " `configure [...] --enable-rapi'.")
71
  print
72
  print qa_utils.FormatWarning(msg)
73

  
74

  
75
def _DoTests(uris):
76
  master = qa_config.GetMasterNode()
77
  host = master["primary"]
78
  port = qa_config.get("rapi-port", default=constants.RAPI_PORT)
79

  
80
  for uri, verify in uris:
81
    assert uri.startswith("/")
82

  
83
    url = "http://%s:%s%s" % (host, port, uri)
84

  
85
    print "Testing %s ..." % url
86

  
87
    response = NoProxyOpener.open(url)
88

  
89
    AssertEqual(response.info()["Content-type"], "application/json")
90

  
91
    data = serializer.LoadJson(response.read())
92

  
93
    if verify is not None:
94
      if callable(verify):
95
        verify(data)
96
      else:
97
        AssertEqual(data, verify)
98

  
99

  
100
@qa_utils.DefineHook('rapi-version')
101
def TestVersion():
102
  """Testing remote API version.
103

  
104
  """
105
  _DoTests([
106
    ("/version", constants.RAPI_VERSION),
107
    ])
108

  
109

  
110
@qa_utils.DefineHook('rapi-empty-cluster')
111
def TestEmptyCluster():
112
  """Testing remote API on an empty cluster.
113

  
114
  """
115
  master_name = qa_config.GetMasterNode()["primary"]
116

  
117
  def _VerifyInfo(data):
118
    AssertIn("name", data)
119
    AssertIn("master", data)
120
    AssertEqual(data["master"], master_name)
121

  
122
  def _VerifyNodes(data):
123
    master_entry = {
124
      "name": master_name,
125
      "uri": "/nodes/%s" % master_name,
126
      }
127
    AssertIn(master_entry, data)
128

  
129
  def _VerifyNodesBulk(data):
130
    for node in data:
131
      for entry in NODE_FIELDS:
132
        AssertIn(entry, node)
133

  
134
  _DoTests([
135
    ("/", None),
136
    ("/info", _VerifyInfo),
137
    ("/tags", None),
138
    ("/nodes", _VerifyNodes),
139
    ("/nodes?bulk=1", _VerifyNodesBulk),
140
    ("/instances", []),
141
    ("/instances?bulk=1", []),
142
    ("/os", None),
143
    ])
144

  
145

  
146
@qa_utils.DefineHook('rapi-instance')
147
def TestInstance(instance):
148
  """Testing getting instance(s) info via remote API.
149

  
150
  """
151
  def _VerifyInstance(data):
152
    for entry in INSTANCE_FIELDS:
153
      AssertIn(entry, data)
154
  
155
  def _VerifyInstancesList(data):
156
    for instance in data:
157
      for entry in LIST_FIELDS: 
158
        AssertIn(entry, instance)
159
      
160
  def _VerifyInstancesBulk(data):
161
    for instance_data in data:
162
      _VerifyInstance(instance_data)
163

  
164
  _DoTests([
165
    ("/instances/%s" % instance["name"], _VerifyInstance),
166
    ("/instances", _VerifyInstancesList),
167
    ("/instances?bulk=1", _VerifyInstancesBulk),
168
    ])
169

  
170

  
171
@qa_utils.DefineHook('rapi-node')
172
def TestNode(node):
173
  """Testing getting node(s) info via remote API.
174

  
175
  """
176
  def _VerifyNode(data):
177
    for entry in NODE_FIELDS:
178
      AssertIn(entry, data)
179
  
180
  def _VerifyNodesList(data):
181
    for node in data:
182
      for entry in LIST_FIELDS: 
183
        AssertIn(entry, node)
184
  
185
  def _VerifyNodesBulk(data):
186
    for node_data in data:
187
      _VerifyNode(node_data)
188

  
189
  _DoTests([
190
    ("/nodes/%s" % node["primary"], _VerifyNode),
191
    ("/nodes", _VerifyNodesList),
192
    ("/nodes?bulk=1", _VerifyNodesBulk),
193
    ])
194

  
195

  
196
def TestTags(kind, name, tags):
197
  """Tests .../tags resources.
198

  
199
  """
200
  if kind == constants.TAG_CLUSTER:
201
    uri = "/tags"
202
  elif kind == constants.TAG_NODE:
203
    uri = "/nodes/%s/tags" % name
204
  elif kind == constants.TAG_INSTANCE:
205
    uri = "/instances/%s/tags" % name
206
  else:
207
    raise errors.ProgrammerError("Unknown tag kind")
208

  
209
  def _VerifyTags(data):
210
    # Create copies to modify
211
    should = tags[:]
212
    should.sort()
213

  
214
    returned = data[:]
215
    returned.sort()
216
    AssertEqual(should, returned)
217

  
218
  _DoTests([
219
    (uri, _VerifyTags),
220
    ])
b/qa/qa_tags.py
1
#
2
#
3

  
4 1
# Copyright (C) 2007 Google Inc.
5 2
#
6 3
# This program is free software; you can redistribute it and/or modify
......
24 21
"""
25 22

  
26 23
from ganeti import utils
24
from ganeti import constants
27 25

  
28 26
import qa_config
29 27
import qa_utils
28
import qa_rapi
30 29

  
31 30
from qa_utils import AssertEqual, StartSSH
32 31

  
......
34 33
_TEMP_TAG_NAMES = ["TEMP-Ganeti-QA-Tag%d" % i for i in range(3)]
35 34
_TEMP_TAG_RE = r'^TEMP-Ganeti-QA-Tag\d+$'
36 35

  
36
_KIND_TO_COMMAND = {
37
  constants.TAG_CLUSTER: "gnt-cluster",
38
  constants.TAG_NODE: "gnt-node",
39
  constants.TAG_INSTANCE: "gnt-instance",
40
  }
41

  
37 42

  
38
def _TestTags(cmdfn):
43
def _TestTags(kind, name):
39 44
  """Generic function for add-tags.
40 45

  
41 46
  """
42 47
  master = qa_config.GetMasterNode()
43 48

  
49
  def cmdfn(subcmd):
50
    cmd = [_KIND_TO_COMMAND[kind], subcmd]
51

  
52
    if kind != constants.TAG_CLUSTER:
53
      cmd.append(name)
54

  
55
    return cmd
56

  
44 57
  cmd = cmdfn('add-tags') + _TEMP_TAG_NAMES
45 58
  AssertEqual(StartSSH(master['primary'],
46 59
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
......
53 66
  AssertEqual(StartSSH(master['primary'],
54 67
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
55 68

  
69
  if qa_rapi.Enabled():
70
    qa_rapi.TestTags(kind, name, _TEMP_TAG_NAMES)
71

  
56 72
  cmd = cmdfn('remove-tags') + _TEMP_TAG_NAMES
57 73
  AssertEqual(StartSSH(master['primary'],
58 74
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
......
61 77
@qa_utils.DefineHook('tags-cluster')
62 78
def TestClusterTags():
63 79
  """gnt-cluster tags"""
64
  _TestTags(lambda subcmd: ['gnt-cluster', subcmd])
80
  _TestTags(constants.TAG_CLUSTER, "")
65 81

  
66 82

  
67 83
@qa_utils.DefineHook('tags-node')
68 84
def TestNodeTags(node):
69 85
  """gnt-node tags"""
70
  _TestTags(lambda subcmd: ['gnt-node', subcmd, node['primary']])
86
  _TestTags(constants.TAG_NODE, node["primary"])
71 87

  
72 88

  
73 89
@qa_utils.DefineHook('tags-instance')
74 90
def TestInstanceTags(instance):
75 91
  """gnt-instance tags"""
76
  _TestTags(lambda subcmd: ['gnt-instance', subcmd, instance['name']])
92
  _TestTags(constants.TAG_INSTANCE, instance["name"])

Also available in: Unified diff