blob: f82a45c4ed45ea76b9a0265d3241ecc702308b0f [file] [log] [blame]
Justin Shepherd0d9bbd12011-08-11 12:57:44 -05001# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Copyright 2011 OpenStack, LLC
4# All Rights Reserved.
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17
18"""Functional test case against the OpenStack Nova API server"""
19
20import json
21import os
Justin Shepherd0d9bbd12011-08-11 12:57:44 -050022import httplib2
Justin Shepherd0d9bbd12011-08-11 12:57:44 -050023import time
Justin Shepherd0d9bbd12011-08-11 12:57:44 -050024
25from pprint import pprint
26
Soren Hansenec3f7092011-09-08 13:03:42 +020027from kong import tests
Justin Shepherd0d9bbd12011-08-11 12:57:44 -050028
29
30class TestNovaAPI(tests.FunctionalTest):
31 def build_check(self, id):
32 self.result = {}
33 """
34 This is intended to check that a server completes the build process
35 and enters an active state upon creation. Due to reporting errors in
36 the API we are also testing ping and ssh
37 """
38 count = 0
39 path = "http://%s:%s/%s/servers/%s" % (self.nova['host'],
40 self.nova['port'],
41 self.nova['ver'],
42 id)
43 http = httplib2.Http()
44 headers = {'X-Auth-User': '%s' % (self.nova['user']),
45 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
46 response, content = http.request(path, 'GET', headers=headers)
Justin Shepherd5778a252011-08-18 12:15:37 -050047 self.assertEqual(response.status, 200)
Justin Shepherd0d9bbd12011-08-11 12:57:44 -050048 data = json.loads(content)
49
50 # Get Server status exit when active
51 while (data['server']['status'] != 'ACTIVE'):
52 response, content = http.request(path, 'GET', headers=headers)
53 data = json.loads(content)
54 time.sleep(5)
55 count = count + 5
56 self.result['serverid'] = id
57 self.result['status'] = data['server']['status']
58
59 # Get IP Address of newly created server
Justin Shepherdf4457092011-08-17 09:33:20 -050060 addr_name = "private"
61 if 'vmnet' in data['server']['addresses']:
62 ref = data['server']['addresses']['vmnet']
63 if len(ref) > 0:
Soren Hansen826d5df2011-08-29 11:30:40 +020064 addr_name = 'vmnet'
Justin Shepherdf4457092011-08-17 09:33:20 -050065 if 'public' in data['server']['addresses']:
66 ref = data['server']['addresses']['public']
67 if len(ref) > 0:
Soren Hansen826d5df2011-08-29 11:30:40 +020068 addr_name = 'public'
Justin Shepherdf4457092011-08-17 09:33:20 -050069 ref = data['server']['addresses'][addr_name]
70 netaddr = ref[0]['addr']
Justin Shepherd0d9bbd12011-08-11 12:57:44 -050071
72 r = "" . join(os.popen('ping -c5 %s' % (netaddr)).readlines())
73 if r.find('64 bytes') > 1:
74 self.result['ping'] = True
75 else:
76 self.result['ping'] = False
77
78 return self.result
79
80 def test_002_verify_nova_auth(self):
81 if 'keystone' in self.config:
82 path = "http://%s:%s/%s" % (self.keystone['host'],
83 self.keystone['port'],
84 self.keystone['apiver'])
85 headers = {'X-Auth-User': self.keystone['user'],
86 'X-Auth-Key': self.keystone['pass']}
87 else:
88 path = "http://%s:%s/%s" % (self.nova['host'],
89 self.nova['port'],
90 self.nova['ver'])
91 headers = {'X-Auth-User': self.nova['user'],
92 'X-Auth-Key': self.nova['key']}
93
94 http = httplib2.Http()
95 response, content = http.request(path, 'HEAD', headers=headers)
Justin Shepherd5778a252011-08-18 12:15:37 -050096 self.assertEqual(response.status, 204)
Justin Shepherd0d9bbd12011-08-11 12:57:44 -050097 self.assertNotEqual(response['x-auth-token'], '')
98 self.assertNotEqual(response['x-server-management-url'], '')
99
100 # Set up Auth Token for all future API interactions
101 self.nova['X-Auth-Token'] = response['x-auth-token']
102 test_002_verify_nova_auth.tags = ['nova', 'nova-api']
103
104 def test_101_verify_version_selection_default(self):
105 path = "http://%s:%s/" % (self.nova['host'],
106 self.nova['port'])
107 http = httplib2.Http()
108 headers = {'X-Auth-Token': self.nova['X-Auth-Token']}
109 response, content = http.request(path, 'GET', headers=headers)
Justin Shepherd5778a252011-08-18 12:15:37 -0500110 self.assertEqual(response.status, 200)
Justin Shepherd0d9bbd12011-08-11 12:57:44 -0500111 data = json.loads(content)
112 self.assertEqual(len(data['versions']), 2)
113 test_101_verify_version_selection_default.tags = ['nova', 'nova-api']
114
115 def test_102_verify_version_selection_json(self):
116 path = "http://%s:%s/.json" % (self.nova['host'],
117 self.nova['port'])
118 http = httplib2.Http()
119 headers = {'X-Auth-Token': self.nova['X-Auth-Token']}
120 response, content = http.request(path, 'GET', headers=headers)
Justin Shepherd5778a252011-08-18 12:15:37 -0500121 self.assertEqual(response.status, 200)
Justin Shepherd0d9bbd12011-08-11 12:57:44 -0500122 data = json.loads(content)
123 self.assertEqual(len(data['versions']), 2)
124 test_102_verify_version_selection_json.tags = ['nova', 'nova-api']
125
126 def test_103_verify_version_selection_xml(self):
127 path = "http://%s:%s/.xml" % (self.nova['host'],
128 self.nova['port'])
129 http = httplib2.Http()
130 headers = {'X-Auth-Token': self.nova['X-Auth-Token']}
131 response, content = http.request(path, 'GET', headers=headers)
Justin Shepherd5778a252011-08-18 12:15:37 -0500132 self.assertEqual(response.status, 200)
Justin Shepherd0d9bbd12011-08-11 12:57:44 -0500133 self.assertTrue('<versions>' in content)
134 test_103_verify_version_selection_xml.tags = ['nova', 'nova-api']
135
136 def test_104_bad_user_bad_key(self):
137 if 'keystone' in self.config:
138 path = "http://%s:%s/%s" % (self.keystone['host'],
139 self.keystone['port'],
140 self.keystone['apiver'])
141 else:
142 path = "http://%s:%s/%s" % (self.nova['host'],
143 self.nova['port'],
144 self.nova['ver'])
145 http = httplib2.Http()
146 headers = {'X-Auth-User': 'unknown_auth_user',
147 'X-Auth-Key': 'unknown_auth_key'}
148 response, content = http.request(path, 'GET', headers=headers)
149 self.assertEqual(response.status, 401)
150 test_104_bad_user_bad_key.tags = ['nova', 'nova-api']
151
152 def test_105_bad_user_good_key(self):
153 if 'keystone' in self.config:
154 path = "http://%s:%s/%s" % (self.keystone['host'],
155 self.keystone['port'],
156 self.keystone['apiver'])
157 else:
158 path = "http://%s:%s/%s" % (self.nova['host'],
159 self.nova['port'],
160 self.nova['ver'])
161 http = httplib2.Http()
162 headers = {'X-Auth-User': 'unknown_auth_user',
163 'X-Auth-Key': self.nova['key']}
164 response, content = http.request(path, 'GET', headers=headers)
165 self.assertEqual(response.status, 401)
166 test_105_bad_user_good_key.tags = ['nova', 'nova-api']
167
168 def test_106_good_user_bad_key(self):
169 if 'keystone' in self.config:
170 path = "http://%s:%s/%s" % (self.keystone['host'],
171 self.keystone['port'],
172 self.keystone['apiver'])
173 else:
174 path = "http://%s:%s/%s" % (self.nova['host'],
175 self.nova['port'],
176 self.nova['ver'])
177 http = httplib2.Http()
178 headers = {'X-Auth-User': self.nova['user'],
179 'X-Auth-Key': 'unknown_auth_key'}
180 response, content = http.request(path, 'GET', headers=headers)
181 self.assertEqual(response.status, 401)
182 test_106_good_user_bad_key.tags = ['nova', 'nova-api']
183
184 def test_107_no_key(self):
185 if 'keystone' in self.config:
186 path = "http://%s:%s/%s" % (self.keystone['host'],
187 self.keystone['port'],
188 self.keystone['apiver'])
189 else:
190 path = "http://%s:%s/%s" % (self.nova['host'],
191 self.nova['port'],
192 self.nova['ver'])
193 http = httplib2.Http()
194 headers = {'X-Auth-User': self.nova['user']}
195 response, content = http.request(path, 'GET', headers=headers)
196 self.assertEqual(response.status, 401)
197 test_107_no_key.tags = ['nova', 'nova-api']
198
199 def test_108_bad_token(self):
200 if 'keystone' in self.config:
201 path = "http://%s:%s/%s" % (self.keystone['host'],
202 self.keystone['port'],
203 self.keystone['apiver'])
204 else:
205 path = "http://%s:%s/%s" % (self.nova['host'],
206 self.nova['port'],
207 self.nova['ver'])
208 http = httplib2.Http()
209 headers = {'X-Auth-Token': 'unknown_token'}
210 response, content = http.request(path, 'GET', headers=headers)
211 self.assertEqual(response.status, 401)
212 test_108_bad_token.tags = ['nova', 'nova-api']
213
214 def test_109_verify_blank_limits(self):
215 path = "http://%s:%s/%s/limits" % (self.nova['host'],
216 self.nova['port'],
217 self.nova['ver'])
218
219 http = httplib2.Http()
220 headers = {'X-Auth-User': '%s' % (self.nova['user']),
221 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
222 response, content = http.request(path, 'GET', headers=headers)
Justin Shepherd5778a252011-08-18 12:15:37 -0500223 self.assertEqual(response.status, 200)
224 self.assertNotEqual(content, '{"limits": []}')
Justin Shepherd0d9bbd12011-08-11 12:57:44 -0500225 test_109_verify_blank_limits.tags = ['nova', 'nova-api']
226
227 def test_110_list_flavors_v1_1(self):
228 path = "http://%s:%s/%s/flavors" % (self.nova['host'],
229 self.nova['port'],
230 self.nova['ver'])
231 http = httplib2.Http()
232 headers = {'X-Auth-User': '%s' % (self.nova['user']),
233 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
234 response, content = http.request(path, 'GET', headers=headers)
Justin Shepherd5778a252011-08-18 12:15:37 -0500235 self.assertEqual(response.status, 200)
236 self.assertNotEqual(content, '{"flavors": []}')
Justin Shepherd0d9bbd12011-08-11 12:57:44 -0500237 test_110_list_flavors_v1_1.tags = ['nova', 'nova-api']
238
239 def test_111_verify_kernel_active_v1_1(self):
240 # for testing purposes change self.glance['kernel_id'] to an active
241 # kernel image allow for skipping glance tests
242 if not 'kernel_id' in self.glance:
243 self.glance['kernel_id'] = "61"
244
245 path = "http://%s:%s/%s/images/%s" % (self.nova['host'],
246 self.nova['port'],
247 self.nova['ver'],
248 self.glance['kernel_id'])
249 http = httplib2.Http()
250 headers = {'X-Auth-User': '%s' % (self.nova['user']),
251 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
252 response, content = http.request(path, 'GET', headers=headers)
Justin Shepherd5778a252011-08-18 12:15:37 -0500253 self.assertEqual(response.status, 200)
Justin Shepherd0d9bbd12011-08-11 12:57:44 -0500254 data = json.loads(content)
255 self.assertEqual(data['image']['status'], 'ACTIVE')
256 test_111_verify_kernel_active_v1_1.tags = ['nova']
257
258 def test_112_verify_ramdisk_active_v1_1(self):
259 # for testing purposes change self.glance['ramdisk_id'] to an active
260 # ramdisk image, allows you to skip glance tests
261 if not 'ramdisk_id' in self.glance:
262 self.glance['ramdisk_id'] = "62"
263
264 path = "http://%s:%s/%s/images/%s" % (self.nova['host'],
265 self.nova['port'],
266 self.nova['ver'],
267 self.glance['ramdisk_id'])
268 http = httplib2.Http()
269 headers = {'X-Auth-User': '%s' % (self.nova['user']),
270 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
271 response, content = http.request(path, 'GET', headers=headers)
Justin Shepherd5778a252011-08-18 12:15:37 -0500272 self.assertEqual(response.status, 200)
Justin Shepherd0d9bbd12011-08-11 12:57:44 -0500273 data = json.loads(content)
274 self.assertEqual(data['image']['status'], 'ACTIVE')
275 test_112_verify_ramdisk_active_v1_1.tags = ['nova']
276
277 def test_113_verify_image_active_v1_1(self):
278 # for testing purposes change self.glance['image_id'] to an active
279 # image id allows for skipping glance tests
280 if not 'image_id' in self.glance:
281 self.glance['image_id'] = "63"
282
283 path = "http://%s:%s/%s/images/%s" % (self.nova['host'],
284 self.nova['port'],
285 self.nova['ver'],
286 self.glance['image_id'])
287 http = httplib2.Http()
288 headers = {'X-Auth-User': '%s' % (self.nova['user']),
289 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
290 response, content = http.request(path, 'GET', headers=headers)
Justin Shepherd5778a252011-08-18 12:15:37 -0500291 self.assertEqual(response.status, 200)
Justin Shepherd0d9bbd12011-08-11 12:57:44 -0500292 data = json.loads(content)
293 self.assertEqual(data['image']['status'], 'ACTIVE')
294 test_113_verify_image_active_v1_1.tags = ['nova']
295
296 def test_200_create_server(self):
297 path = "http://%s:%s/%s/servers" % (self.nova['host'],
298 self.nova['port'],
299 self.nova['ver'])
300 http = httplib2.Http()
301 headers = {'X-Auth-User': '%s' % (self.nova['user']),
302 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token']),
303 'Content-Type': 'application/json'}
304
305 # Change imageRef to self.glance['image_id']
306 json_str = {"server":
307 {
308 "name": "testing server creation",
309 "flavorRef": "http://%s:%s/%s/flavors/2" % (self.nova['host'],
310 self.nova['port'],
311 self.nova['ver']),
312 "imageRef": self.glance['image_id']
313# "imageRef": "http://%s:%s/%s/images/%s" % (self.nova['host'],
314# self.nova['port'],
315# self.nova['ver'],
316# self.glance['image_id'])
317 }
318 }
Soren Hansenf1bd0532011-09-09 14:25:46 +0200319 pprint(json_str)
Justin Shepherd0d9bbd12011-08-11 12:57:44 -0500320 data = json.dumps(json_str)
321 response, content = http.request(path, 'POST', headers=headers,
322 body=data)
Soren Hansena01ed3a2011-09-09 14:21:01 +0200323 try:
324 json_return = json.loads(content)
325 except ValueError:
326 print repr(content)
327 raise
Justin Shepherd5778a252011-08-18 12:15:37 -0500328 self.assertEqual(response.status, 200)
Justin Shepherd0d9bbd12011-08-11 12:57:44 -0500329 self.assertEqual(json_return['server']['status'], "BUILD")
330 self.nova['single_server_id'] = json_return['server']['id']
331 time.sleep(5)
332 build_result = self.build_check(self.nova['single_server_id'])
333 self.assertEqual(build_result['status'], "ACTIVE")
334 self.assertEqual(build_result['ping'], True)
335 test_200_create_server.tags = ['nova']
336
337 def test_201_get_server_details(self):
338 path = "http://%s:%s/%s/servers/%s" % (self.nova['host'],
339 self.nova['port'],
340 self.nova['ver'],
341 self.nova['single_server_id'])
342
343 http = httplib2.Http()
344 headers = {'X-Auth-User': '%s' % (self.nova['user']),
345 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
346
347 response, content = http.request(path, 'GET', headers=headers)
Justin Shepherd5778a252011-08-18 12:15:37 -0500348 self.assertEqual(response.status, 200)
Justin Shepherd0d9bbd12011-08-11 12:57:44 -0500349 test_201_get_server_details.tags = ['nova']
350
351 # MOVING TO 999 because it can kill the API
352 # Uncomment next line for testing
353 # def create_multi(self):
354 def test_999_create_multiple(self):
355 self.nova['multi_server'] = {}
356 path = "http://%s:%s/%s/servers" % (self.nova['host'],
357 self.nova['port'],
358 self.nova['ver'])
359 http = httplib2.Http()
360 headers = {'X-Auth-User': '%s' % (self.nova['user']),
361 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token']),
362 'Content-Type': 'application/json'}
363
364 for i in range(1, 10):
365 # Change imageRef to self.glance['image_id']
366 json_str = {"server":
367 {
368 "name": "test %s" % (i),
369 "flavorRef": "http://%s:%s/%s/flavors/2" % (
370 self.nova['host'],
371 self.nova['port'],
372 self.nova['ver']),
373 "imageRef": self.glance['image_id']
374# "imageRef": "http://%s:%s/%s/images/%s" % (
375# self.nova['host'],
376# self.nova['port'],
377# self.nova['ver'],
378# self.glance['image_id'])
379 }
380 }
381 data = json.dumps(json_str)
382 response, content = http.request(path, 'POST', headers=headers,
383 body=data)
384 json_return = json.loads(content)
Justin Shepherd5778a252011-08-18 12:15:37 -0500385 self.assertEqual(response.status, 200)
Justin Shepherd0d9bbd12011-08-11 12:57:44 -0500386 self.assertEqual(json_return['server']['status'], "BUILD")
387 self.nova['multi_server']["test %s" % (i)] = \
388 json_return['server']['id']
389 time.sleep(30)
390
391 for k, v in self.nova['multi_server'].iteritems():
392 build_result = self.build_check(v)
393 self.assertEqual(build_result['ping'], True)
394 test_999_create_multiple.tags = ['nova']