blob: 5e27194adf3f1482937e117d2e6a0be9da7351fb [file] [log] [blame]
Soren Hansenbc1d3a02011-09-08 13:33:17 +02001
2import base64
3import json
4import os
5
Soren Hansenbc1d3a02011-09-08 13:33:17 +02006from kong import openstack
7from kong import exceptions
Soren Hansen6adacc82011-09-09 13:34:35 +02008from kong import tests
Soren Hansenbc1d3a02011-09-08 13:33:17 +02009from kong.common import ssh
10
11
Soren Hansen6adacc82011-09-09 13:34:35 +020012class ServersTest(tests.FunctionalTest):
Soren Hansen4480f602011-09-09 16:12:35 +020013 def setUp(self):
Soren Hansen6adacc82011-09-09 13:34:35 +020014 super(ServersTest, self).setUp()
Soren Hansend6b047a2011-09-09 13:39:32 +020015 self.os = openstack.Manager(self.nova)
Soren Hansena86180a2011-09-09 16:22:26 +020016 self.image_ref = self.glance['image_id']
17 self.flavor_ref = self.nova['flavor_ref']
18 self.ssh_timeout = self.nova['ssh_timeout']
19 self.build_timeout = self.nova['build_timeout']
Soren Hansenbc1d3a02011-09-08 13:33:17 +020020
Aaron Lee35b8c922011-10-18 17:07:19 -050021 def tearDown(self):
22 if getattr(self, 'server_id', False):
23 self.os.nova.delete_server(self.server_id)
24
Soren Hansenbc1d3a02011-09-08 13:33:17 +020025 def _assert_server_entity(self, server):
26 actual_keys = set(server.keys())
27 expected_keys = set((
28 'id',
29 'name',
30 'hostId',
31 'status',
32 'metadata',
33 'addresses',
34 'links',
35 'progress',
36 'image',
37 'flavor',
38 'created',
39 'updated',
40 'accessIPv4',
41 'accessIPv6',
42
43 #KNOWN-ISSUE lp804093
44 'uuid',
45
46 ))
47 self.assertTrue(expected_keys <= actual_keys)
48
49 server_id = str(server['id'])
Soren Hansena86180a2011-09-09 16:22:26 +020050 host = self.nova['host']
51 port = self.nova['port']
Soren Hansenbc1d3a02011-09-08 13:33:17 +020052 api_url = '%s:%s' % (host, port)
Soren Hansena86180a2011-09-09 16:22:26 +020053 base_url = os.path.join(api_url, self.nova['apiver'])
Soren Hansenbc1d3a02011-09-08 13:33:17 +020054
55 self_link = 'http://' + os.path.join(base_url,
Aaron Lee35b8c922011-10-18 17:07:19 -050056 self.os.nova.project_id,
Soren Hansenbc1d3a02011-09-08 13:33:17 +020057 'servers', server_id)
58 bookmark_link = 'http://' + os.path.join(api_url,
Aaron Lee35b8c922011-10-18 17:07:19 -050059 self.os.nova.project_id,
Soren Hansenbc1d3a02011-09-08 13:33:17 +020060 'servers', server_id)
61
62 expected_links = [
63 {
64 'rel': 'self',
65 'href': self_link,
66 },
67 {
68 'rel': 'bookmark',
69 'href': bookmark_link,
70 },
71 ]
72
73 self.assertEqual(server['links'], expected_links)
74
75 def test_build_server(self):
76 """Build a server"""
77
78 expected_server = {
79 'name': 'testserver',
80 'metadata': {
81 'key1': 'value1',
82 'key2': 'value2',
83 },
84 'imageRef': self.image_ref,
85 'flavorRef': self.flavor_ref,
86 }
87
88 post_body = json.dumps({'server': expected_server})
89 response, body = self.os.nova.request('POST',
90 '/servers',
91 body=post_body)
92
93 self.assertEqual(response.status, 202)
94
95 _body = json.loads(body)
96 self.assertEqual(_body.keys(), ['server'])
97 created_server = _body['server']
Aaron Lee35b8c922011-10-18 17:07:19 -050098 self.server_id = created_server['id'] # for the tearDown
Soren Hansenbc1d3a02011-09-08 13:33:17 +020099
100 admin_pass = created_server.pop('adminPass')
101 self._assert_server_entity(created_server)
102 self.assertEqual(expected_server['name'], created_server['name'])
103 self.assertEqual(expected_server['metadata'],
104 created_server['metadata'])
105
106 self.os.nova.wait_for_server_status(created_server['id'],
107 'ACTIVE',
108 timeout=self.build_timeout)
109
110 server = self.os.nova.get_server(created_server['id'])
111
112 # Find IP of server
113 try:
114 (_, network) = server['addresses'].popitem()
115 ip = network[0]['addr']
116 except KeyError:
117 self.fail("Failed to retrieve IP address from server entity")
118
119 # Assert password works
Aaron Lee35b8c922011-10-18 17:07:19 -0500120 if int(self.nova['ssh_timeout']) > 0:
121 client = ssh.Client(ip, 'root', admin_pass, self.ssh_timeout)
122 self.assertTrue(client.test_connection_auth())
Soren Hansenfce58c52011-09-09 16:07:13 +0200123 test_build_server.tags = ['nova', 'glance']
Soren Hansenbc1d3a02011-09-08 13:33:17 +0200124
125 def test_build_server_with_file(self):
126 """Build a server with an injected file"""
127
128 file_contents = 'testing'
129
130 expected_server = {
131 'name': 'testserver',
132 'metadata': {
133 'key1': 'value1',
134 'key2': 'value2',
135 },
136 'personality': [
137 {
138 'path': '/etc/test.txt',
139 'contents': base64.b64encode(file_contents),
140 },
141 ],
142 'imageRef': self.image_ref,
143 'flavorRef': self.flavor_ref,
144 }
145
146 post_body = json.dumps({'server': expected_server})
147 response, body = self.os.nova.request('POST',
148 '/servers',
149 body=post_body)
150
151 self.assertEqual(response.status, 202)
152
153 _body = json.loads(body)
154 self.assertEqual(_body.keys(), ['server'])
155 created_server = _body['server']
Aaron Lee35b8c922011-10-18 17:07:19 -0500156 self.server_id = _body['server']['id']
Soren Hansenbc1d3a02011-09-08 13:33:17 +0200157
158 admin_pass = created_server.pop('adminPass', None)
159 self._assert_server_entity(created_server)
160 self.assertEqual(expected_server['name'], created_server['name'])
161 self.assertEqual(expected_server['metadata'],
162 created_server['metadata'])
163
164 self.os.nova.wait_for_server_status(created_server['id'],
165 'ACTIVE',
166 timeout=self.build_timeout)
167
168 server = self.os.nova.get_server(created_server['id'])
169
170 # Find IP of server
171 try:
172 (_, network) = server['addresses'].popitem()
173 ip = network[0]['addr']
174 except KeyError:
175 self.fail("Failed to retrieve IP address from server entity")
176
177 # Assert injected file is on instance, also verifying password works
Aaron Lee35b8c922011-10-18 17:07:19 -0500178 if int(self.nova['ssh_timeout']) > 0:
179 client = ssh.Client(ip, 'root', admin_pass, self.ssh_timeout)
180 injected_file = client.exec_command('cat /etc/test.txt')
181 self.assertEqual(injected_file, file_contents)
Soren Hansenfce58c52011-09-09 16:07:13 +0200182 test_build_server_with_file.tags = ['nova', 'glance']
Soren Hansenbc1d3a02011-09-08 13:33:17 +0200183
184 def test_build_server_with_password(self):
185 """Build a server with a password"""
186
187 server_password = 'testpwd'
188
189 expected_server = {
190 'name': 'testserver',
191 'metadata': {
192 'key1': 'value1',
193 'key2': 'value2',
194 },
195 'adminPass': server_password,
196 'imageRef': self.image_ref,
197 'flavorRef': self.flavor_ref,
198 }
199
200 post_body = json.dumps({'server': expected_server})
201 response, body = self.os.nova.request('POST',
202 '/servers',
203 body=post_body)
204
205 self.assertEqual(response.status, 202)
206
207 _body = json.loads(body)
208 self.assertEqual(_body.keys(), ['server'])
209 created_server = _body['server']
210
211 admin_pass = created_server.pop('adminPass', None)
212 self._assert_server_entity(created_server)
213 self.assertEqual(expected_server['name'], created_server['name'])
214 self.assertEqual(expected_server['adminPass'], admin_pass)
215 self.assertEqual(expected_server['metadata'],
216 created_server['metadata'])
217
218 self.os.nova.wait_for_server_status(created_server['id'],
219 'ACTIVE',
220 timeout=self.build_timeout)
221
222 server = self.os.nova.get_server(created_server['id'])
223
224 # Find IP of server
225 try:
226 (_, network) = server['addresses'].popitem()
227 ip = network[0]['addr']
228 except KeyError:
229 self.fail("Failed to retrieve IP address from server entity")
230
Aaron Lee35b8c922011-10-18 17:07:19 -0500231 # Assert password was set to that in request ( if ssh_timeout is > 0
232 if int(self.nova['ssh_timeout']) > 0:
233 client = ssh.Client(ip, 'root', server_password, self.ssh_timeout)
234 self.assertTrue(client.test_connection_auth())
Soren Hansenfce58c52011-09-09 16:07:13 +0200235 test_build_server_with_password.tags = ['nova', 'glance']
Soren Hansenbc1d3a02011-09-08 13:33:17 +0200236
237 def test_delete_server_building(self):
238 """Delete a server while building"""
239
240 # Make create server request
241 server = {
242 'name' : 'testserver',
243 'imageRef' : self.image_ref,
244 'flavorRef' : self.flavor_ref,
245 }
246 created_server = self.os.nova.create_server(server)
247
248 # Server should immediately be accessible, but in have building status
249 server = self.os.nova.get_server(created_server['id'])
250 self.assertEqual(server['status'], 'BUILD')
251
252 self.os.nova.delete_server(created_server['id'])
253
254 # Poll server until deleted
255 try:
256 url = '/servers/%s' % created_server['id']
257 self.os.nova.poll_request_status('GET', url, 404)
258 except exceptions.TimeoutException:
259 self.fail("Server deletion timed out")
Soren Hansenfce58c52011-09-09 16:07:13 +0200260 test_delete_server_building.tags = ['nova', 'glance']
Soren Hansenbc1d3a02011-09-08 13:33:17 +0200261
262 def test_delete_server_active(self):
263 """Delete a server after fully built"""
264
265 expected_server = {
266 'name' : 'testserver',
267 'imageRef' : self.image_ref,
268 'flavorRef' : self.flavor_ref,
269 }
270
271 created_server = self.os.nova.create_server(expected_server)
272 server_id = created_server['id']
273
274 self.os.nova.wait_for_server_status(server_id,
275 'ACTIVE',
276 timeout=self.build_timeout)
277
278 self.os.nova.delete_server(server_id)
279
280 # Poll server until deleted
281 try:
282 url = '/servers/%s' % server_id
283 self.os.nova.poll_request_status('GET', url, 404)
284 except exceptions.TimeoutException:
285 self.fail("Server deletion timed out")
Soren Hansenfce58c52011-09-09 16:07:13 +0200286 test_delete_server_active.tags = ['nova', 'glance']
Soren Hansenbc1d3a02011-09-08 13:33:17 +0200287
288 def test_update_server_name(self):
289 """Change the name of a server"""
290
291 expected_server = {
292 'name' : 'testserver',
293 'imageRef' : self.image_ref,
294 'flavorRef' : self.flavor_ref,
295 }
296
297 created_server = self.os.nova.create_server(expected_server)
298
299 self.assertTrue(expected_server['name'], created_server['name'])
300 server_id = created_server['id']
301
302 # Wait for it to be built
303 self.os.nova.wait_for_server_status(server_id,
304 'ACTIVE',
305 timeout=self.build_timeout)
306
307 # Update name
308 new_server = {'name': 'updatedtestserver'}
309 put_body = json.dumps({
310 'server': new_server,
311 })
312 url = '/servers/%s' % server_id
313 resp, body = self.os.nova.request('PUT', url, body=put_body)
314
315 self.assertEqual(resp.status, 200)
316 data = json.loads(body)
317 self.assertEqual(data.keys(), ['server'])
318 self._assert_server_entity(data['server'])
319 self.assertEqual('updatedtestserver', data['server']['name'])
320
321 # Get Server information
322 resp, body = self.os.nova.request('GET', '/servers/%s' % server_id)
323 self.assertEqual(200, resp.status)
324 data = json.loads(body)
325 self.assertEqual(data.keys(), ['server'])
326 self._assert_server_entity(data['server'])
327 self.assertEqual('updatedtestserver', data['server']['name'])
328
329 self.os.nova.delete_server(server_id)
Soren Hansenfce58c52011-09-09 16:07:13 +0200330 test_update_server_name.tags = ['nova', 'glance']
Soren Hansenbc1d3a02011-09-08 13:33:17 +0200331
332 def test_create_server_invalid_image(self):
333 """Create a server with an unknown image"""
334
335 post_body = json.dumps({
336 'server' : {
337 'name' : 'testserver',
338 'imageRef' : -1,
339 'flavorRef' : self.flavor_ref,
340 }
341 })
342
343 resp, body = self.os.nova.request('POST', '/servers', body=post_body)
344
345 self.assertEqual(400, resp.status)
346
347 fault = json.loads(body)
348 expected_fault = {
349 "badRequest": {
350 "message": "Cannot find requested image",
351 "code": 400,
352 },
353 }
354 # KNOWN-ISSUE - The error message is confusing and should be improved
355 #self.assertEqual(fault, expected_fault)
Soren Hansenfce58c52011-09-09 16:07:13 +0200356 test_create_server_invalid_image.tags = ['nova', 'glance']
Soren Hansenbc1d3a02011-09-08 13:33:17 +0200357
358 def test_create_server_invalid_flavor(self):
359 """Create a server with an unknown flavor"""
360
361 post_body = json.dumps({
362 'server' : {
363 'name' : 'testserver',
364 'imageRef' : self.image_ref,
365 'flavorRef' : -1,
366 }
367 })
368
369 resp, body = self.os.nova.request('POST', '/servers', body=post_body)
370
371 self.assertEqual(400, resp.status)
372
373 fault = json.loads(body)
374 expected_fault = {
375 "badRequest": {
376 "message": "Cannot find requested flavor",
377 "code": 400,
378 },
379 }
380 # KNOWN-ISSUE lp804084
381 #self.assertEqual(fault, expected_fault)
Soren Hansenfce58c52011-09-09 16:07:13 +0200382 test_create_server_invalid_flavor.tags = ['nova', 'glance']