Remove QA hook functionality
[ganeti-local] / 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 def TestVersion():
101   """Testing remote API version.
102
103   """
104   _DoTests([
105     ("/version", constants.RAPI_VERSION),
106     ])
107
108
109 def TestEmptyCluster():
110   """Testing remote API on an empty cluster.
111
112   """
113   master_name = qa_config.GetMasterNode()["primary"]
114
115   def _VerifyInfo(data):
116     AssertIn("name", data)
117     AssertIn("master", data)
118     AssertEqual(data["master"], master_name)
119
120   def _VerifyNodes(data):
121     master_entry = {
122       "name": master_name,
123       "uri": "/nodes/%s" % master_name,
124       }
125     AssertIn(master_entry, data)
126
127   def _VerifyNodesBulk(data):
128     for node in data:
129       for entry in NODE_FIELDS:
130         AssertIn(entry, node)
131
132   _DoTests([
133     ("/", None),
134     ("/info", _VerifyInfo),
135     ("/tags", None),
136     ("/nodes", _VerifyNodes),
137     ("/nodes?bulk=1", _VerifyNodesBulk),
138     ("/instances", []),
139     ("/instances?bulk=1", []),
140     ("/os", None),
141     ])
142
143
144 def TestInstance(instance):
145   """Testing getting instance(s) info via remote API.
146
147   """
148   def _VerifyInstance(data):
149     for entry in INSTANCE_FIELDS:
150       AssertIn(entry, data)
151   
152   def _VerifyInstancesList(data):
153     for instance in data:
154       for entry in LIST_FIELDS: 
155         AssertIn(entry, instance)
156       
157   def _VerifyInstancesBulk(data):
158     for instance_data in data:
159       _VerifyInstance(instance_data)
160
161   _DoTests([
162     ("/instances/%s" % instance["name"], _VerifyInstance),
163     ("/instances", _VerifyInstancesList),
164     ("/instances?bulk=1", _VerifyInstancesBulk),
165     ])
166
167
168 def TestNode(node):
169   """Testing getting node(s) info via remote API.
170
171   """
172   def _VerifyNode(data):
173     for entry in NODE_FIELDS:
174       AssertIn(entry, data)
175   
176   def _VerifyNodesList(data):
177     for node in data:
178       for entry in LIST_FIELDS: 
179         AssertIn(entry, node)
180   
181   def _VerifyNodesBulk(data):
182     for node_data in data:
183       _VerifyNode(node_data)
184
185   _DoTests([
186     ("/nodes/%s" % node["primary"], _VerifyNode),
187     ("/nodes", _VerifyNodesList),
188     ("/nodes?bulk=1", _VerifyNodesBulk),
189     ])
190
191
192 def TestTags(kind, name, tags):
193   """Tests .../tags resources.
194
195   """
196   if kind == constants.TAG_CLUSTER:
197     uri = "/tags"
198   elif kind == constants.TAG_NODE:
199     uri = "/nodes/%s/tags" % name
200   elif kind == constants.TAG_INSTANCE:
201     uri = "/instances/%s/tags" % name
202   else:
203     raise errors.ProgrammerError("Unknown tag kind")
204
205   def _VerifyTags(data):
206     # Create copies to modify
207     should = tags[:]
208     should.sort()
209
210     returned = data[:]
211     returned.sort()
212     AssertEqual(should, returned)
213
214   _DoTests([
215     (uri, _VerifyTags),
216     ])