blob: 36d071d97cbef5dcb77218e4c24376a1c74a1afa [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
22import tempfile
23import unittest
24import httplib2
25import urllib
26import hashlib
27import time
28import os
29
30from pprint import pprint
31
32import tests
33
34
35class TestNovaAPI(tests.FunctionalTest):
36 def build_check(self, id):
37 self.result = {}
38 """
39 This is intended to check that a server completes the build process
40 and enters an active state upon creation. Due to reporting errors in
41 the API we are also testing ping and ssh
42 """
43 count = 0
44 path = "http://%s:%s/%s/servers/%s" % (self.nova['host'],
45 self.nova['port'],
46 self.nova['ver'],
47 id)
48 http = httplib2.Http()
49 headers = {'X-Auth-User': '%s' % (self.nova['user']),
50 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
51 response, content = http.request(path, 'GET', headers=headers)
52 self.assertEqual(200, response.status)
53 data = json.loads(content)
54
55 # Get Server status exit when active
56 while (data['server']['status'] != 'ACTIVE'):
57 response, content = http.request(path, 'GET', headers=headers)
58 data = json.loads(content)
59 time.sleep(5)
60 count = count + 5
61 self.result['serverid'] = id
62 self.result['status'] = data['server']['status']
63
64 # Get IP Address of newly created server
65 if 'addr' in data['server']['addresses']['vmnet'][0]:
66 netaddr = data['server']['addresses']['vmnet'][0]['addr']
67 elif 'addr' in data['server']['address']['public'][0]:
68 netaddr = data['server']['addresses']['public'][0]['addr']
69
70 r = "" . join(os.popen('ping -c5 %s' % (netaddr)).readlines())
71 if r.find('64 bytes') > 1:
72 self.result['ping'] = True
73 else:
74 self.result['ping'] = False
75
76 return self.result
77
78 def test_002_verify_nova_auth(self):
79 if 'keystone' in self.config:
80 path = "http://%s:%s/%s" % (self.keystone['host'],
81 self.keystone['port'],
82 self.keystone['apiver'])
83 headers = {'X-Auth-User': self.keystone['user'],
84 'X-Auth-Key': self.keystone['pass']}
85 else:
86 path = "http://%s:%s/%s" % (self.nova['host'],
87 self.nova['port'],
88 self.nova['ver'])
89 headers = {'X-Auth-User': self.nova['user'],
90 'X-Auth-Key': self.nova['key']}
91
92 http = httplib2.Http()
93 response, content = http.request(path, 'HEAD', headers=headers)
94 self.assertEqual(204, response.status)
95 self.assertNotEqual(response['x-auth-token'], '')
96 self.assertNotEqual(response['x-server-management-url'], '')
97
98 # Set up Auth Token for all future API interactions
99 self.nova['X-Auth-Token'] = response['x-auth-token']
100 test_002_verify_nova_auth.tags = ['nova', 'nova-api']
101
102 def test_101_verify_version_selection_default(self):
103 path = "http://%s:%s/" % (self.nova['host'],
104 self.nova['port'])
105 http = httplib2.Http()
106 headers = {'X-Auth-Token': self.nova['X-Auth-Token']}
107 response, content = http.request(path, 'GET', headers=headers)
108 self.assertEqual(200, response.status)
109 data = json.loads(content)
110 self.assertEqual(len(data['versions']), 2)
111 test_101_verify_version_selection_default.tags = ['nova', 'nova-api']
112
113 def test_102_verify_version_selection_json(self):
114 path = "http://%s:%s/.json" % (self.nova['host'],
115 self.nova['port'])
116 http = httplib2.Http()
117 headers = {'X-Auth-Token': self.nova['X-Auth-Token']}
118 response, content = http.request(path, 'GET', headers=headers)
119 self.assertEqual(200, response.status)
120 data = json.loads(content)
121 self.assertEqual(len(data['versions']), 2)
122 test_102_verify_version_selection_json.tags = ['nova', 'nova-api']
123
124 def test_103_verify_version_selection_xml(self):
125 path = "http://%s:%s/.xml" % (self.nova['host'],
126 self.nova['port'])
127 http = httplib2.Http()
128 headers = {'X-Auth-Token': self.nova['X-Auth-Token']}
129 response, content = http.request(path, 'GET', headers=headers)
130 self.assertEqual(200, response.status)
131 self.assertTrue('<versions>' in content)
132 test_103_verify_version_selection_xml.tags = ['nova', 'nova-api']
133
134 def test_104_bad_user_bad_key(self):
135 if 'keystone' in self.config:
136 path = "http://%s:%s/%s" % (self.keystone['host'],
137 self.keystone['port'],
138 self.keystone['apiver'])
139 else:
140 path = "http://%s:%s/%s" % (self.nova['host'],
141 self.nova['port'],
142 self.nova['ver'])
143 http = httplib2.Http()
144 headers = {'X-Auth-User': 'unknown_auth_user',
145 'X-Auth-Key': 'unknown_auth_key'}
146 response, content = http.request(path, 'GET', headers=headers)
147 self.assertEqual(response.status, 401)
148 test_104_bad_user_bad_key.tags = ['nova', 'nova-api']
149
150 def test_105_bad_user_good_key(self):
151 if 'keystone' in self.config:
152 path = "http://%s:%s/%s" % (self.keystone['host'],
153 self.keystone['port'],
154 self.keystone['apiver'])
155 else:
156 path = "http://%s:%s/%s" % (self.nova['host'],
157 self.nova['port'],
158 self.nova['ver'])
159 http = httplib2.Http()
160 headers = {'X-Auth-User': 'unknown_auth_user',
161 'X-Auth-Key': self.nova['key']}
162 response, content = http.request(path, 'GET', headers=headers)
163 self.assertEqual(response.status, 401)
164 test_105_bad_user_good_key.tags = ['nova', 'nova-api']
165
166 def test_106_good_user_bad_key(self):
167 if 'keystone' in self.config:
168 path = "http://%s:%s/%s" % (self.keystone['host'],
169 self.keystone['port'],
170 self.keystone['apiver'])
171 else:
172 path = "http://%s:%s/%s" % (self.nova['host'],
173 self.nova['port'],
174 self.nova['ver'])
175 http = httplib2.Http()
176 headers = {'X-Auth-User': self.nova['user'],
177 'X-Auth-Key': 'unknown_auth_key'}
178 response, content = http.request(path, 'GET', headers=headers)
179 self.assertEqual(response.status, 401)
180 test_106_good_user_bad_key.tags = ['nova', 'nova-api']
181
182 def test_107_no_key(self):
183 if 'keystone' in self.config:
184 path = "http://%s:%s/%s" % (self.keystone['host'],
185 self.keystone['port'],
186 self.keystone['apiver'])
187 else:
188 path = "http://%s:%s/%s" % (self.nova['host'],
189 self.nova['port'],
190 self.nova['ver'])
191 http = httplib2.Http()
192 headers = {'X-Auth-User': self.nova['user']}
193 response, content = http.request(path, 'GET', headers=headers)
194 self.assertEqual(response.status, 401)
195 test_107_no_key.tags = ['nova', 'nova-api']
196
197 def test_108_bad_token(self):
198 if 'keystone' in self.config:
199 path = "http://%s:%s/%s" % (self.keystone['host'],
200 self.keystone['port'],
201 self.keystone['apiver'])
202 else:
203 path = "http://%s:%s/%s" % (self.nova['host'],
204 self.nova['port'],
205 self.nova['ver'])
206 http = httplib2.Http()
207 headers = {'X-Auth-Token': 'unknown_token'}
208 response, content = http.request(path, 'GET', headers=headers)
209 self.assertEqual(response.status, 401)
210 test_108_bad_token.tags = ['nova', 'nova-api']
211
212 def test_109_verify_blank_limits(self):
213 path = "http://%s:%s/%s/limits" % (self.nova['host'],
214 self.nova['port'],
215 self.nova['ver'])
216
217 http = httplib2.Http()
218 headers = {'X-Auth-User': '%s' % (self.nova['user']),
219 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
220 response, content = http.request(path, 'GET', headers=headers)
221 self.assertEqual(200, response.status)
222 self.assertNotEqual('{"limits": []}', content)
223 test_109_verify_blank_limits.tags = ['nova', 'nova-api']
224
225 def test_110_list_flavors_v1_1(self):
226 path = "http://%s:%s/%s/flavors" % (self.nova['host'],
227 self.nova['port'],
228 self.nova['ver'])
229 http = httplib2.Http()
230 headers = {'X-Auth-User': '%s' % (self.nova['user']),
231 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
232 response, content = http.request(path, 'GET', headers=headers)
233 self.assertEqual(200, response.status)
234 self.assertNotEqual('{"flavors": []}', content)
235 test_110_list_flavors_v1_1.tags = ['nova', 'nova-api']
236
237 def test_111_verify_kernel_active_v1_1(self):
238 # for testing purposes change self.glance['kernel_id'] to an active
239 # kernel image allow for skipping glance tests
240 if not 'kernel_id' in self.glance:
241 self.glance['kernel_id'] = "61"
242
243 path = "http://%s:%s/%s/images/%s" % (self.nova['host'],
244 self.nova['port'],
245 self.nova['ver'],
246 self.glance['kernel_id'])
247 http = httplib2.Http()
248 headers = {'X-Auth-User': '%s' % (self.nova['user']),
249 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
250 response, content = http.request(path, 'GET', headers=headers)
251 self.assertEqual(200, response.status)
252 data = json.loads(content)
253 self.assertEqual(data['image']['status'], 'ACTIVE')
254 test_111_verify_kernel_active_v1_1.tags = ['nova']
255
256 def test_112_verify_ramdisk_active_v1_1(self):
257 # for testing purposes change self.glance['ramdisk_id'] to an active
258 # ramdisk image, allows you to skip glance tests
259 if not 'ramdisk_id' in self.glance:
260 self.glance['ramdisk_id'] = "62"
261
262 path = "http://%s:%s/%s/images/%s" % (self.nova['host'],
263 self.nova['port'],
264 self.nova['ver'],
265 self.glance['ramdisk_id'])
266 http = httplib2.Http()
267 headers = {'X-Auth-User': '%s' % (self.nova['user']),
268 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
269 response, content = http.request(path, 'GET', headers=headers)
270 self.assertEqual(200, response.status)
271 data = json.loads(content)
272 self.assertEqual(data['image']['status'], 'ACTIVE')
273 test_112_verify_ramdisk_active_v1_1.tags = ['nova']
274
275 def test_113_verify_image_active_v1_1(self):
276 # for testing purposes change self.glance['image_id'] to an active
277 # image id allows for skipping glance tests
278 if not 'image_id' in self.glance:
279 self.glance['image_id'] = "63"
280
281 path = "http://%s:%s/%s/images/%s" % (self.nova['host'],
282 self.nova['port'],
283 self.nova['ver'],
284 self.glance['image_id'])
285 http = httplib2.Http()
286 headers = {'X-Auth-User': '%s' % (self.nova['user']),
287 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
288 response, content = http.request(path, 'GET', headers=headers)
289 self.assertEqual(200, response.status)
290 data = json.loads(content)
291 self.assertEqual(data['image']['status'], 'ACTIVE')
292 test_113_verify_image_active_v1_1.tags = ['nova']
293
294 def test_200_create_server(self):
295 path = "http://%s:%s/%s/servers" % (self.nova['host'],
296 self.nova['port'],
297 self.nova['ver'])
298 http = httplib2.Http()
299 headers = {'X-Auth-User': '%s' % (self.nova['user']),
300 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token']),
301 'Content-Type': 'application/json'}
302
303 # Change imageRef to self.glance['image_id']
304 json_str = {"server":
305 {
306 "name": "testing server creation",
307 "flavorRef": "http://%s:%s/%s/flavors/2" % (self.nova['host'],
308 self.nova['port'],
309 self.nova['ver']),
310 "imageRef": self.glance['image_id']
311# "imageRef": "http://%s:%s/%s/images/%s" % (self.nova['host'],
312# self.nova['port'],
313# self.nova['ver'],
314# self.glance['image_id'])
315 }
316 }
317 data = json.dumps(json_str)
318 response, content = http.request(path, 'POST', headers=headers,
319 body=data)
320 json_return = json.loads(content)
321 self.assertEqual(200, response.status)
322 self.assertEqual(json_return['server']['status'], "BUILD")
323 self.nova['single_server_id'] = json_return['server']['id']
324 time.sleep(5)
325 build_result = self.build_check(self.nova['single_server_id'])
326 self.assertEqual(build_result['status'], "ACTIVE")
327 self.assertEqual(build_result['ping'], True)
328 test_200_create_server.tags = ['nova']
329
330 def test_201_get_server_details(self):
331 path = "http://%s:%s/%s/servers/%s" % (self.nova['host'],
332 self.nova['port'],
333 self.nova['ver'],
334 self.nova['single_server_id'])
335
336 http = httplib2.Http()
337 headers = {'X-Auth-User': '%s' % (self.nova['user']),
338 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
339
340 response, content = http.request(path, 'GET', headers=headers)
341 self.assertEqual(200, response.status)
342 test_201_get_server_details.tags = ['nova']
343
344 # MOVING TO 999 because it can kill the API
345 # Uncomment next line for testing
346 # def create_multi(self):
347 def test_999_create_multiple(self):
348 self.nova['multi_server'] = {}
349 path = "http://%s:%s/%s/servers" % (self.nova['host'],
350 self.nova['port'],
351 self.nova['ver'])
352 http = httplib2.Http()
353 headers = {'X-Auth-User': '%s' % (self.nova['user']),
354 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token']),
355 'Content-Type': 'application/json'}
356
357 for i in range(1, 10):
358 # Change imageRef to self.glance['image_id']
359 json_str = {"server":
360 {
361 "name": "test %s" % (i),
362 "flavorRef": "http://%s:%s/%s/flavors/2" % (
363 self.nova['host'],
364 self.nova['port'],
365 self.nova['ver']),
366 "imageRef": self.glance['image_id']
367# "imageRef": "http://%s:%s/%s/images/%s" % (
368# self.nova['host'],
369# self.nova['port'],
370# self.nova['ver'],
371# self.glance['image_id'])
372 }
373 }
374 data = json.dumps(json_str)
375 response, content = http.request(path, 'POST', headers=headers,
376 body=data)
377 json_return = json.loads(content)
378 self.assertEqual(200, response.status)
379 self.assertEqual(json_return['server']['status'], "BUILD")
380 self.nova['multi_server']["test %s" % (i)] = \
381 json_return['server']['id']
382 time.sleep(30)
383
384 for k, v in self.nova['multi_server'].iteritems():
385 build_result = self.build_check(v)
386 self.assertEqual(build_result['ping'], True)
387 test_999_create_multiple.tags = ['nova']