3 # Copyright (C) 2007, 2008 Google Inc.
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.
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.
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
21 """Remote API QA tests.
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
34 import ganeti.rapi.client
35 import ganeti.rapi.client_utils
41 from qa_utils import (AssertEqual, AssertNotEqual, AssertIn, AssertMatch,
49 def Setup(username, password):
50 """Configures the RAPI client.
56 master = qa_config.GetMasterNode()
58 # Load RAPI certificate from master node
59 cmd = ["cat", constants.RAPI_CERT_FILE]
61 # Write to temporary file
62 _rapi_ca = tempfile.NamedTemporaryFile()
63 _rapi_ca.write(qa_utils.GetCommandOutput(master["primary"],
64 utils.ShellQuoteArgs(cmd)))
67 port = qa_config.get("rapi-port", default=constants.DEFAULT_RAPI_PORT)
68 cfg_ssl = rapi.client.CertAuthorityVerify(cafile=_rapi_ca.name)
70 _rapi_client = rapi.client.GanetiRapiClient(master["primary"], port=port,
73 config_ssl_verification=cfg_ssl,
76 print "RAPI protocol version: %s" % _rapi_client.GetVersion()
79 INSTANCE_FIELDS = ("name", "os", "pnode", "snodes",
81 "disk_template", "disk.sizes",
82 "nic.ips", "nic.macs", "nic.modes", "nic.links",
83 "beparams", "hvparams",
84 "oper_state", "oper_ram", "status", "tags")
86 NODE_FIELDS = ("name", "dtotal", "dfree",
87 "mtotal", "mnode", "mfree",
88 "pinst_cnt", "sinst_cnt", "tags")
90 JOB_FIELDS = frozenset([
91 "id", "ops", "status", "summary",
92 "opstatus", "opresult", "oplog",
93 "received_ts", "start_ts", "end_ts",
96 LIST_FIELDS = ("id", "uri")
100 """Return whether remote API tests should be run.
103 return qa_config.TestEnabled('rapi')
109 for uri, verify, method, body in uris:
110 assert uri.startswith("/")
112 data = _rapi_client._SendRequest(method, uri, None, body)
114 if verify is not None:
118 AssertEqual(data, verify)
125 def _VerifyReturnsJob(data):
126 AssertMatch(data, r'^\d+$')
130 """Testing remote API version.
134 ("/version", constants.RAPI_VERSION, 'GET', None),
138 def TestEmptyCluster():
139 """Testing remote API on an empty cluster.
142 master = qa_config.GetMasterNode()
143 master_full = qa_utils.ResolveNodeName(master)
145 def _VerifyInfo(data):
146 AssertIn("name", data)
147 AssertIn("master", data)
148 AssertEqual(data["master"], master_full)
150 def _VerifyNodes(data):
153 "uri": "/2/nodes/%s" % master_full,
155 AssertIn(master_entry, data)
157 def _VerifyNodesBulk(data):
159 for entry in NODE_FIELDS:
160 AssertIn(entry, node)
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),
174 def TestInstance(instance):
175 """Testing getting instance(s) info via remote API.
178 def _VerifyInstance(data):
179 for entry in INSTANCE_FIELDS:
180 AssertIn(entry, data)
182 def _VerifyInstancesList(data):
183 for instance in data:
184 for entry in LIST_FIELDS:
185 AssertIn(entry, instance)
187 def _VerifyInstancesBulk(data):
188 for instance_data in data:
189 _VerifyInstance(instance_data)
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),
203 """Testing getting node(s) info via remote API.
206 def _VerifyNode(data):
207 for entry in NODE_FIELDS:
208 AssertIn(entry, data)
210 def _VerifyNodesList(data):
212 for entry in LIST_FIELDS:
213 AssertIn(entry, node)
215 def _VerifyNodesBulk(data):
216 for node_data in data:
217 _VerifyNode(node_data)
220 ("/2/nodes/%s" % node["primary"], _VerifyNode, 'GET', None),
221 ("/2/nodes", _VerifyNodesList, 'GET', None),
222 ("/2/nodes?bulk=1", _VerifyNodesBulk, 'GET', None),
226 def TestTags(kind, name, tags):
227 """Tests .../tags resources.
230 if kind == constants.TAG_CLUSTER:
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
237 raise errors.ProgrammerError("Unknown tag kind")
239 def _VerifyTags(data):
240 AssertEqual(sorted(tags), sorted(data))
243 (uri, _VerifyTags, 'GET', None),
247 def _WaitForRapiJob(job_id):
248 """Waits for a job to finish.
251 master = qa_config.GetMasterNode()
253 def _VerifyJob(data):
254 AssertEqual(data["id"], job_id)
255 for field in JOB_FIELDS:
256 AssertIn(field, data)
259 ("/2/jobs/%s" % job_id, _VerifyJob, "GET", None),
262 rapi.client_utils.PollJob(_rapi_client, job_id, cli.StdioJobPollReportCb())
265 def TestRapiInstanceAdd(node):
266 """Test adding a new instance via RAPI"""
267 instance = qa_config.AcquireInstance()
270 "name": instance["name"],
271 "os": qa_config.get("os"),
272 "disk_template": constants.DT_PLAIN,
273 "pnode": node["primary"],
274 "memory": utils.ParseUnit(qa_config.get("mem")),
275 "disks": [utils.ParseUnit(size) for size in qa_config.get("disk")],
278 (job_id, ) = _DoTests([
279 ("/2/instances", _VerifyReturnsJob, "POST", body),
282 _WaitForRapiJob(job_id)
286 qa_config.ReleaseInstance(instance)
290 def TestRapiInstanceRemove(instance):
291 """Test removing instance via RAPI"""
292 (job_id, ) = _DoTests([
293 ("/2/instances/%s" % instance["name"], _VerifyReturnsJob, "DELETE", None),
296 _WaitForRapiJob(job_id)
298 qa_config.ReleaseInstance(instance)