blob: fa2eae69aa605224501f012905d45731aecda419 [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 Hansenbc1d3a02011-09-08 13:33:17 +020013
14 @classmethod
15 def setUpClass(self):
Soren Hansen6adacc82011-09-09 13:34:35 +020016 super(ServersTest, self).setUp()
Soren Hansend6b047a2011-09-09 13:39:32 +020017 self.os = openstack.Manager(self.nova)
Soren Hansenbc1d3a02011-09-08 13:33:17 +020018 self.image_ref = self.os.config.env.image_ref
19 self.flavor_ref = self.os.config.env.flavor_ref
20 self.ssh_timeout = self.os.config.nova.ssh_timeout
21 self.build_timeout = self.os.config.nova.build_timeout
22
23 def _assert_server_entity(self, server):
24 actual_keys = set(server.keys())
25 expected_keys = set((
26 'id',
27 'name',
28 'hostId',
29 'status',
30 'metadata',
31 'addresses',
32 'links',
33 'progress',
34 'image',
35 'flavor',
36 'created',
37 'updated',
38 'accessIPv4',
39 'accessIPv6',
40
41 #KNOWN-ISSUE lp804093
42 'uuid',
43
44 ))
45 self.assertTrue(expected_keys <= actual_keys)
46
47 server_id = str(server['id'])
48 host = self.os.config.nova.host
49 port = self.os.config.nova.port
50 api_url = '%s:%s' % (host, port)
51 base_url = os.path.join(api_url, self.os.config.nova.base_url)
52
53 self_link = 'http://' + os.path.join(base_url,
54 self.os.config.nova.project_id,
55 'servers', server_id)
56 bookmark_link = 'http://' + os.path.join(api_url,
57 self.os.config.nova.project_id,
58 'servers', server_id)
59
60 expected_links = [
61 {
62 'rel': 'self',
63 'href': self_link,
64 },
65 {
66 'rel': 'bookmark',
67 'href': bookmark_link,
68 },
69 ]
70
71 self.assertEqual(server['links'], expected_links)
72
73 def test_build_server(self):
74 """Build a server"""
75
76 expected_server = {
77 'name': 'testserver',
78 'metadata': {
79 'key1': 'value1',
80 'key2': 'value2',
81 },
82 'imageRef': self.image_ref,
83 'flavorRef': self.flavor_ref,
84 }
85
86 post_body = json.dumps({'server': expected_server})
87 response, body = self.os.nova.request('POST',
88 '/servers',
89 body=post_body)
90
91 self.assertEqual(response.status, 202)
92
93 _body = json.loads(body)
94 self.assertEqual(_body.keys(), ['server'])
95 created_server = _body['server']
96
97 admin_pass = created_server.pop('adminPass')
98 self._assert_server_entity(created_server)
99 self.assertEqual(expected_server['name'], created_server['name'])
100 self.assertEqual(expected_server['metadata'],
101 created_server['metadata'])
102
103 self.os.nova.wait_for_server_status(created_server['id'],
104 'ACTIVE',
105 timeout=self.build_timeout)
106
107 server = self.os.nova.get_server(created_server['id'])
108
109 # Find IP of server
110 try:
111 (_, network) = server['addresses'].popitem()
112 ip = network[0]['addr']
113 except KeyError:
114 self.fail("Failed to retrieve IP address from server entity")
115
116 # Assert password works
117 client = ssh.Client(ip, 'root', admin_pass, self.ssh_timeout)
118 self.assertTrue(client.test_connection_auth())
119
120 self.os.nova.delete_server(server['id'])
121
122 def test_build_server_with_file(self):
123 """Build a server with an injected file"""
124
125 file_contents = 'testing'
126
127 expected_server = {
128 'name': 'testserver',
129 'metadata': {
130 'key1': 'value1',
131 'key2': 'value2',
132 },
133 'personality': [
134 {
135 'path': '/etc/test.txt',
136 'contents': base64.b64encode(file_contents),
137 },
138 ],
139 'imageRef': self.image_ref,
140 'flavorRef': self.flavor_ref,
141 }
142
143 post_body = json.dumps({'server': expected_server})
144 response, body = self.os.nova.request('POST',
145 '/servers',
146 body=post_body)
147
148 self.assertEqual(response.status, 202)
149
150 _body = json.loads(body)
151 self.assertEqual(_body.keys(), ['server'])
152 created_server = _body['server']
153
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
174 client = ssh.Client(ip, 'root', admin_pass, self.ssh_timeout)
175 injected_file = client.exec_command('cat /etc/test.txt')
176 self.assertEqual(injected_file, file_contents)
177
178 self.os.nova.delete_server(server['id'])
179
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
227 # Assert password was set to that in request
228 client = ssh.Client(ip, 'root', server_password, self.ssh_timeout)
229 self.assertTrue(client.test_connection_auth())
230
231 self.os.nova.delete_server(server['id'])
232
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")
256
257 def test_delete_server_active(self):
258 """Delete a server after fully built"""
259
260 expected_server = {
261 'name' : 'testserver',
262 'imageRef' : self.image_ref,
263 'flavorRef' : self.flavor_ref,
264 }
265
266 created_server = self.os.nova.create_server(expected_server)
267 server_id = created_server['id']
268
269 self.os.nova.wait_for_server_status(server_id,
270 'ACTIVE',
271 timeout=self.build_timeout)
272
273 self.os.nova.delete_server(server_id)
274
275 # Poll server until deleted
276 try:
277 url = '/servers/%s' % server_id
278 self.os.nova.poll_request_status('GET', url, 404)
279 except exceptions.TimeoutException:
280 self.fail("Server deletion timed out")
281
282 def test_update_server_name(self):
283 """Change the name of a server"""
284
285 expected_server = {
286 'name' : 'testserver',
287 'imageRef' : self.image_ref,
288 'flavorRef' : self.flavor_ref,
289 }
290
291 created_server = self.os.nova.create_server(expected_server)
292
293 self.assertTrue(expected_server['name'], created_server['name'])
294 server_id = created_server['id']
295
296 # Wait for it to be built
297 self.os.nova.wait_for_server_status(server_id,
298 'ACTIVE',
299 timeout=self.build_timeout)
300
301 # Update name
302 new_server = {'name': 'updatedtestserver'}
303 put_body = json.dumps({
304 'server': new_server,
305 })
306 url = '/servers/%s' % server_id
307 resp, body = self.os.nova.request('PUT', url, body=put_body)
308
309 self.assertEqual(resp.status, 200)
310 data = json.loads(body)
311 self.assertEqual(data.keys(), ['server'])
312 self._assert_server_entity(data['server'])
313 self.assertEqual('updatedtestserver', data['server']['name'])
314
315 # Get Server information
316 resp, body = self.os.nova.request('GET', '/servers/%s' % server_id)
317 self.assertEqual(200, resp.status)
318 data = json.loads(body)
319 self.assertEqual(data.keys(), ['server'])
320 self._assert_server_entity(data['server'])
321 self.assertEqual('updatedtestserver', data['server']['name'])
322
323 self.os.nova.delete_server(server_id)
324
325 def test_create_server_invalid_image(self):
326 """Create a server with an unknown image"""
327
328 post_body = json.dumps({
329 'server' : {
330 'name' : 'testserver',
331 'imageRef' : -1,
332 'flavorRef' : self.flavor_ref,
333 }
334 })
335
336 resp, body = self.os.nova.request('POST', '/servers', body=post_body)
337
338 self.assertEqual(400, resp.status)
339
340 fault = json.loads(body)
341 expected_fault = {
342 "badRequest": {
343 "message": "Cannot find requested image",
344 "code": 400,
345 },
346 }
347 # KNOWN-ISSUE - The error message is confusing and should be improved
348 #self.assertEqual(fault, expected_fault)
349
350 def test_create_server_invalid_flavor(self):
351 """Create a server with an unknown flavor"""
352
353 post_body = json.dumps({
354 'server' : {
355 'name' : 'testserver',
356 'imageRef' : self.image_ref,
357 'flavorRef' : -1,
358 }
359 })
360
361 resp, body = self.os.nova.request('POST', '/servers', body=post_body)
362
363 self.assertEqual(400, resp.status)
364
365 fault = json.loads(body)
366 expected_fault = {
367 "badRequest": {
368 "message": "Cannot find requested flavor",
369 "code": 400,
370 },
371 }
372 # KNOWN-ISSUE lp804084
373 #self.assertEqual(fault, expected_fault)