blob: f81f6a2ccf9763ec83a30dc5f52cb32ae1e209de [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((
Soren Hansenbc1d3a02011-09-08 13:33:17 +020028 'accessIPv4',
29 'accessIPv6',
Aaron Lee84d2f132011-10-25 11:47:47 -050030 'addresses',
31 'created',
32 'flavor',
33 'hostId',
34 'id',
35 'image',
36 'links',
37 'metadata',
38 'name',
39 'progress',
40 'status',
41 'updated',
Soren Hansenbc1d3a02011-09-08 13:33:17 +020042 ))
43 self.assertTrue(expected_keys <= actual_keys)
44
45 server_id = str(server['id'])
Soren Hansena86180a2011-09-09 16:22:26 +020046 host = self.nova['host']
47 port = self.nova['port']
Soren Hansenbc1d3a02011-09-08 13:33:17 +020048 api_url = '%s:%s' % (host, port)
Soren Hansena86180a2011-09-09 16:22:26 +020049 base_url = os.path.join(api_url, self.nova['apiver'])
Soren Hansenbc1d3a02011-09-08 13:33:17 +020050
51 self_link = 'http://' + os.path.join(base_url,
Aaron Lee35b8c922011-10-18 17:07:19 -050052 self.os.nova.project_id,
Soren Hansenbc1d3a02011-09-08 13:33:17 +020053 'servers', server_id)
54 bookmark_link = 'http://' + os.path.join(api_url,
Aaron Lee35b8c922011-10-18 17:07:19 -050055 self.os.nova.project_id,
Soren Hansenbc1d3a02011-09-08 13:33:17 +020056 'servers', server_id)
57
58 expected_links = [
59 {
60 'rel': 'self',
61 'href': self_link,
62 },
63 {
64 'rel': 'bookmark',
65 'href': bookmark_link,
66 },
67 ]
68
69 self.assertEqual(server['links'], expected_links)
70
71 def test_build_server(self):
72 """Build a server"""
73
74 expected_server = {
75 'name': 'testserver',
76 'metadata': {
77 'key1': 'value1',
78 'key2': 'value2',
79 },
80 'imageRef': self.image_ref,
81 'flavorRef': self.flavor_ref,
82 }
83
84 post_body = json.dumps({'server': expected_server})
85 response, body = self.os.nova.request('POST',
86 '/servers',
87 body=post_body)
88
89 self.assertEqual(response.status, 202)
90
91 _body = json.loads(body)
92 self.assertEqual(_body.keys(), ['server'])
93 created_server = _body['server']
Aaron Lee35b8c922011-10-18 17:07:19 -050094 self.server_id = created_server['id'] # for the tearDown
Soren Hansenbc1d3a02011-09-08 13:33:17 +020095
96 admin_pass = created_server.pop('adminPass')
97 self._assert_server_entity(created_server)
98 self.assertEqual(expected_server['name'], created_server['name'])
99 self.assertEqual(expected_server['metadata'],
100 created_server['metadata'])
101
102 self.os.nova.wait_for_server_status(created_server['id'],
103 'ACTIVE',
104 timeout=self.build_timeout)
105
106 server = self.os.nova.get_server(created_server['id'])
107
108 # Find IP of server
109 try:
110 (_, network) = server['addresses'].popitem()
111 ip = network[0]['addr']
112 except KeyError:
113 self.fail("Failed to retrieve IP address from server entity")
114
115 # Assert password works
Aaron Lee35b8c922011-10-18 17:07:19 -0500116 if int(self.nova['ssh_timeout']) > 0:
117 client = ssh.Client(ip, 'root', admin_pass, self.ssh_timeout)
118 self.assertTrue(client.test_connection_auth())
Soren Hansenfce58c52011-09-09 16:07:13 +0200119 test_build_server.tags = ['nova', 'glance']
Soren Hansenbc1d3a02011-09-08 13:33:17 +0200120
121 def test_build_server_with_file(self):
122 """Build a server with an injected file"""
123
124 file_contents = 'testing'
125
126 expected_server = {
127 'name': 'testserver',
128 'metadata': {
129 'key1': 'value1',
130 'key2': 'value2',
131 },
132 'personality': [
133 {
134 'path': '/etc/test.txt',
135 'contents': base64.b64encode(file_contents),
136 },
137 ],
138 'imageRef': self.image_ref,
139 'flavorRef': self.flavor_ref,
140 }
141
142 post_body = json.dumps({'server': expected_server})
143 response, body = self.os.nova.request('POST',
144 '/servers',
145 body=post_body)
146
147 self.assertEqual(response.status, 202)
148
149 _body = json.loads(body)
150 self.assertEqual(_body.keys(), ['server'])
151 created_server = _body['server']
Aaron Lee35b8c922011-10-18 17:07:19 -0500152 self.server_id = _body['server']['id']
Soren Hansenbc1d3a02011-09-08 13:33:17 +0200153
154 admin_pass = created_server.pop('adminPass', None)
155 self._assert_server_entity(created_server)
156 self.assertEqual(expected_server['name'], created_server['name'])
157 self.assertEqual(expected_server['metadata'],
158 created_server['metadata'])
159
160 self.os.nova.wait_for_server_status(created_server['id'],
161 'ACTIVE',
162 timeout=self.build_timeout)
163
164 server = self.os.nova.get_server(created_server['id'])
165
166 # Find IP of server
167 try:
168 (_, network) = server['addresses'].popitem()
169 ip = network[0]['addr']
170 except KeyError:
171 self.fail("Failed to retrieve IP address from server entity")
172
173 # Assert injected file is on instance, also verifying password works
Aaron Lee35b8c922011-10-18 17:07:19 -0500174 if int(self.nova['ssh_timeout']) > 0:
175 client = ssh.Client(ip, 'root', admin_pass, self.ssh_timeout)
176 injected_file = client.exec_command('cat /etc/test.txt')
177 self.assertEqual(injected_file, file_contents)
Soren Hansenfce58c52011-09-09 16:07:13 +0200178 test_build_server_with_file.tags = ['nova', 'glance']
Soren Hansenbc1d3a02011-09-08 13:33:17 +0200179
180 def test_build_server_with_password(self):
181 """Build a server with a password"""
182
183 server_password = 'testpwd'
184
185 expected_server = {
186 'name': 'testserver',
187 'metadata': {
188 'key1': 'value1',
189 'key2': 'value2',
190 },
191 'adminPass': server_password,
192 'imageRef': self.image_ref,
193 'flavorRef': self.flavor_ref,
194 }
195
196 post_body = json.dumps({'server': expected_server})
197 response, body = self.os.nova.request('POST',
198 '/servers',
199 body=post_body)
200
201 self.assertEqual(response.status, 202)
202
203 _body = json.loads(body)
204 self.assertEqual(_body.keys(), ['server'])
205 created_server = _body['server']
206
207 admin_pass = created_server.pop('adminPass', None)
208 self._assert_server_entity(created_server)
209 self.assertEqual(expected_server['name'], created_server['name'])
210 self.assertEqual(expected_server['adminPass'], admin_pass)
211 self.assertEqual(expected_server['metadata'],
212 created_server['metadata'])
213
214 self.os.nova.wait_for_server_status(created_server['id'],
215 'ACTIVE',
216 timeout=self.build_timeout)
217
218 server = self.os.nova.get_server(created_server['id'])
219
220 # Find IP of server
221 try:
222 (_, network) = server['addresses'].popitem()
223 ip = network[0]['addr']
224 except KeyError:
225 self.fail("Failed to retrieve IP address from server entity")
226
Aaron Lee35b8c922011-10-18 17:07:19 -0500227 # Assert password was set to that in request ( if ssh_timeout is > 0
228 if int(self.nova['ssh_timeout']) > 0:
229 client = ssh.Client(ip, 'root', server_password, self.ssh_timeout)
230 self.assertTrue(client.test_connection_auth())
Soren Hansenfce58c52011-09-09 16:07:13 +0200231 test_build_server_with_password.tags = ['nova', 'glance']
Soren Hansenbc1d3a02011-09-08 13:33:17 +0200232
233 def test_delete_server_building(self):
234 """Delete a server while building"""
235
236 # Make create server request
237 server = {
238 'name' : 'testserver',
239 'imageRef' : self.image_ref,
240 'flavorRef' : self.flavor_ref,
241 }
242 created_server = self.os.nova.create_server(server)
243
244 # Server should immediately be accessible, but in have building status
245 server = self.os.nova.get_server(created_server['id'])
246 self.assertEqual(server['status'], 'BUILD')
247
248 self.os.nova.delete_server(created_server['id'])
249
250 # Poll server until deleted
251 try:
252 url = '/servers/%s' % created_server['id']
253 self.os.nova.poll_request_status('GET', url, 404)
254 except exceptions.TimeoutException:
255 self.fail("Server deletion timed out")
Soren Hansenfce58c52011-09-09 16:07:13 +0200256 test_delete_server_building.tags = ['nova', 'glance']
Soren Hansenbc1d3a02011-09-08 13:33:17 +0200257
258 def test_delete_server_active(self):
259 """Delete a server after fully built"""
260
261 expected_server = {
262 'name' : 'testserver',
263 'imageRef' : self.image_ref,
264 'flavorRef' : self.flavor_ref,
265 }
266
267 created_server = self.os.nova.create_server(expected_server)
268 server_id = created_server['id']
269
270 self.os.nova.wait_for_server_status(server_id,
271 'ACTIVE',
272 timeout=self.build_timeout)
273
274 self.os.nova.delete_server(server_id)
275
276 # Poll server until deleted
277 try:
278 url = '/servers/%s' % server_id
279 self.os.nova.poll_request_status('GET', url, 404)
280 except exceptions.TimeoutException:
281 self.fail("Server deletion timed out")
Soren Hansenfce58c52011-09-09 16:07:13 +0200282 test_delete_server_active.tags = ['nova', 'glance']
Soren Hansenbc1d3a02011-09-08 13:33:17 +0200283
284 def test_update_server_name(self):
285 """Change the name of a server"""
286
287 expected_server = {
288 'name' : 'testserver',
289 'imageRef' : self.image_ref,
290 'flavorRef' : self.flavor_ref,
291 }
292
293 created_server = self.os.nova.create_server(expected_server)
294
295 self.assertTrue(expected_server['name'], created_server['name'])
296 server_id = created_server['id']
297
298 # Wait for it to be built
299 self.os.nova.wait_for_server_status(server_id,
300 'ACTIVE',
301 timeout=self.build_timeout)
302
303 # Update name
304 new_server = {'name': 'updatedtestserver'}
305 put_body = json.dumps({
306 'server': new_server,
307 })
308 url = '/servers/%s' % server_id
309 resp, body = self.os.nova.request('PUT', url, body=put_body)
310
311 self.assertEqual(resp.status, 200)
312 data = json.loads(body)
313 self.assertEqual(data.keys(), ['server'])
314 self._assert_server_entity(data['server'])
315 self.assertEqual('updatedtestserver', data['server']['name'])
316
317 # Get Server information
318 resp, body = self.os.nova.request('GET', '/servers/%s' % server_id)
319 self.assertEqual(200, resp.status)
320 data = json.loads(body)
321 self.assertEqual(data.keys(), ['server'])
322 self._assert_server_entity(data['server'])
323 self.assertEqual('updatedtestserver', data['server']['name'])
324
325 self.os.nova.delete_server(server_id)
Soren Hansenfce58c52011-09-09 16:07:13 +0200326 test_update_server_name.tags = ['nova', 'glance']
Soren Hansenbc1d3a02011-09-08 13:33:17 +0200327
328 def test_create_server_invalid_image(self):
329 """Create a server with an unknown image"""
330
331 post_body = json.dumps({
332 'server' : {
333 'name' : 'testserver',
334 'imageRef' : -1,
335 'flavorRef' : self.flavor_ref,
336 }
337 })
338
339 resp, body = self.os.nova.request('POST', '/servers', body=post_body)
340
341 self.assertEqual(400, resp.status)
342
343 fault = json.loads(body)
344 expected_fault = {
345 "badRequest": {
346 "message": "Cannot find requested image",
347 "code": 400,
348 },
349 }
350 # KNOWN-ISSUE - The error message is confusing and should be improved
351 #self.assertEqual(fault, expected_fault)
Soren Hansenfce58c52011-09-09 16:07:13 +0200352 test_create_server_invalid_image.tags = ['nova', 'glance']
Soren Hansenbc1d3a02011-09-08 13:33:17 +0200353
354 def test_create_server_invalid_flavor(self):
355 """Create a server with an unknown flavor"""
356
357 post_body = json.dumps({
358 'server' : {
359 'name' : 'testserver',
360 'imageRef' : self.image_ref,
361 'flavorRef' : -1,
362 }
363 })
364
365 resp, body = self.os.nova.request('POST', '/servers', body=post_body)
366
367 self.assertEqual(400, resp.status)
368
369 fault = json.loads(body)
370 expected_fault = {
371 "badRequest": {
372 "message": "Cannot find requested flavor",
373 "code": 400,
374 },
375 }
376 # KNOWN-ISSUE lp804084
377 #self.assertEqual(fault, expected_fault)
Soren Hansenfce58c52011-09-09 16:07:13 +0200378 test_create_server_invalid_flavor.tags = ['nova', 'glance']