Revision 47eeffa9
b/snf-cyclades-app/synnefo/api/tests.py | ||
---|---|---|
1 |
# Copyright 2011 GRNET S.A. All rights reserved.
|
|
1 |
# Copyright 2012 GRNET S.A. All rights reserved.
|
|
2 | 2 |
# |
3 | 3 |
# Redistribution and use in source and binary forms, with or |
4 | 4 |
# without modification, are permitted provided that the following |
... | ... | |
33 | 33 |
|
34 | 34 |
from __future__ import with_statement |
35 | 35 |
|
36 |
from collections import defaultdict |
|
37 |
from email.utils import parsedate |
|
38 |
from random import choice, randint, sample |
|
39 |
from time import mktime |
|
40 |
|
|
41 |
from django.conf import settings |
|
42 | 36 |
from django.utils import simplejson as json |
43 | 37 |
from django.test import TestCase |
44 | 38 |
from django.test.client import Client |
... | ... | |
46 | 40 |
from synnefo.db.models import * |
47 | 41 |
from synnefo.logic.utils import get_rsapi_state |
48 | 42 |
|
49 |
import mock |
|
50 |
from synnefo.lib import astakos |
|
43 |
from mock import patch, Mock |
|
51 | 44 |
|
52 | 45 |
from contextlib import contextmanager |
46 |
from synnefo.db import models_factory as mfactory |
|
47 |
|
|
48 |
from synnefo.api import util |
|
49 |
from synnefo.api import faults |
|
50 |
|
|
51 |
|
|
52 |
def get_image_mock(request, *Args, **kwargs): |
|
53 |
return {'backend_id': '1234', |
|
54 |
'location': 'pithos://dummyimage', |
|
55 |
'disk_format': 'drbd'} |
|
56 |
util.get_image = get_image_mock |
|
53 | 57 |
|
54 |
# This is a hack to override astakos |
|
55 |
# The global variable ASTAKOS_PATCHED_USER keeps the name of |
|
56 |
# a dummy user that we provide through replacement of the |
|
57 |
# corresponding astakos function with a dummy function. |
|
58 |
ASTAKOS_PATCHED_USER = "user" |
|
59 | 58 |
|
60 | 59 |
@contextmanager |
61 | 60 |
def astakos_user(user): |
... | ... | |
64 | 63 |
|
65 | 64 |
usage: |
66 | 65 |
with astakos_user("user@user.com"): |
67 |
.... make api calls .... get_user will act as user@user.com requested the api.
|
|
66 |
.... make api calls .... |
|
68 | 67 |
|
69 | 68 |
""" |
70 | 69 |
from synnefo.lib import astakos |
70 |
from synnefo.api import util |
|
71 | 71 |
orig_method = astakos.get_user |
72 |
|
|
73 |
global ASTAKOS_PATCHED_USER |
|
74 |
ASTAKOS_PATCHED_USER = user |
|
72 |
|
|
75 | 73 |
def dummy_get_user(request, *args, **kwargs): |
76 |
global ASTAKOS_PATCHED_USER |
|
77 |
request.user = {'username': ASTAKOS_PATCHED_USER, 'groups': []} |
|
78 |
request.user_uniq = ASTAKOS_PATCHED_USER |
|
74 |
request.user = {'username': user, 'groups': []} |
|
75 |
request.user_uniq = user |
|
79 | 76 |
astakos.get_user = dummy_get_user |
77 |
util.get_user = dummy_get_user |
|
80 | 78 |
yield |
81 | 79 |
astakos.get_user = orig_method |
82 | 80 |
|
81 |
|
|
83 | 82 |
class AaiClient(Client): |
84 | 83 |
def request(self, **request): |
85 | 84 |
request['HTTP_X_AUTH_TOKEN'] = '0000' |
86 | 85 |
return super(AaiClient, self).request(**request) |
87 | 86 |
|
88 |
class NetworksTest(TestCase): |
|
89 |
|
|
90 |
fixtures = ['network_test_data'] |
|
91 |
|
|
92 |
def test_attachments_list(self): |
|
93 |
with astakos_user("admin@adminland.com"): |
|
94 |
r = self.client.get("/api/v1.1/networks") |
|
95 |
data = json.loads(r.content) |
|
96 |
self.assertEqual(data["networks"]["values"][1]["name"], "network4admin") |
|
97 |
#import pdb; pdb.set_trace() |
|
98 |
self.assertEqual(len(data["networks"]["values"]), 2) |
|
99 |
with astakos_user("user1@userland.com"): |
|
100 |
r = self.client.get("/api/v1.1/networks") |
|
101 |
data = json.loads(r.content) |
|
102 |
self.assertEqual(data["networks"]["values"][1]["name"], "network4user1") |
|
103 |
#import pdb; pdb.set_trace() |
|
104 |
self.assertEqual(len(data["networks"]["values"]), 2) |
|
105 |
|
|
106 |
def test_create_network(self): |
|
107 |
with astakos_user("admin@adminland.com"): |
|
108 |
r = self.client.post("/api/v1.1/networks") |
|
109 |
|
|
110 |
class ServersTest(TestCase): |
|
111 |
|
|
112 |
fixtures = ['network_test_data'] |
|
113 |
|
|
114 |
def test_attachments_list(self): |
|
115 |
with astakos_user("admin@adminland.com"): |
|
116 |
r = self.client.get("/api/v1.1/servers") |
|
117 |
data = json.loads(r.content) |
|
118 |
self.assertEqual(data["servers"]["values"][0]["id"], 1001) |
|
119 |
self.assertEqual(len(data["servers"]["values"]), 1) |
|
120 |
r = self.client.get("/api/v1.1/servers/1001") |
|
121 |
|
|
122 |
|
|
123 |
class TestQuota(TestCase): |
|
124 | 87 |
|
125 |
fixtures = ['users', 'flavors'] |
|
126 |
astakos_response_user = 'test' |
|
127 |
|
|
128 |
def setUp(self): |
|
129 |
|
|
130 |
self.astakos_response_user = 'test' |
|
131 |
def get_user_mock(request, *Args, **kwargs): |
|
132 |
if request.META.get('HTTP_X_AUTH_TOKEN', None) == '0000': |
|
133 |
request.user_uniq = self.astakos_response_user |
|
134 |
request.user = {'uniq': self.astakos_response_user} |
|
135 |
|
|
136 |
def get_image_mock(request, *Args, **kwargs): |
|
137 |
return {'backend_id':'1234', 'location':'pithos://dummyimage', |
|
138 |
'disk_format': 'plain'} |
|
139 |
|
|
140 |
self.rapi_patch = mock.patch('synnefo.logic.backend.rapi') |
|
141 |
self.rapi_mock = self.rapi_patch.start() |
|
142 |
|
|
143 |
self.pithos_patch = mock.patch('synnefo.api.util.get_image') |
|
144 |
self.pithos_mock = self.rapi_patch.start() |
|
145 |
|
|
146 |
# mock the astakos authentication function |
|
147 |
from synnefo.api import util |
|
148 |
util.get_user = get_user_mock |
|
149 |
util.get_image = get_image_mock |
|
150 |
|
|
151 |
settings.SKIP_SSH_VALIDATION = True |
|
152 |
self.client = AaiClient() |
|
153 |
self.user = 'test' |
|
154 |
|
|
155 |
def test_vms_quota(self): |
|
156 |
request = { |
|
157 |
"server": { |
|
158 |
"name": "new-server-test", |
|
159 |
"userid": "test", |
|
160 |
"imageRef": 1, |
|
161 |
"flavorRef": 1, |
|
162 |
"metadata": { |
|
163 |
"My Server Name": "Apache1" |
|
164 |
}, |
|
165 |
"personality": [] |
|
166 |
} |
|
167 |
} |
|
88 |
def create_flavors(num): |
|
89 |
return [mfactory.FlavorFactory() for x in range(num)] |
|
168 | 90 |
|
169 |
def create_server(for_user='test'): |
|
170 |
self.astakos_response_user = for_user |
|
171 |
return self.client.post('/api/v1.1/servers', json.dumps(request), |
|
172 |
content_type="application/json") |
|
173 |
|
|
174 |
def user_vms_count(user='test'): |
|
175 |
return VirtualMachine.objects.filter(userid=user).count() |
|
176 |
|
|
177 |
# admin sets max vms per user to 2 |
|
178 |
settings.MAX_VMS_PER_USER = 2 |
|
179 |
create_server() |
|
180 |
create_server() |
|
181 |
self.assertEqual(user_vms_count(), 2) |
|
182 |
|
|
183 |
# third creation fails |
|
184 |
resp = create_server() |
|
185 |
self.assertEqual(resp.status_code, 413) |
|
186 |
self.assertEqual(user_vms_count(), 2) |
|
187 |
|
|
188 |
# setting changed, no additional servers can get created |
|
189 |
settings.MAX_VMS_PER_USER = 1 |
|
190 |
resp = create_server() |
|
191 |
self.assertEqual(resp.status_code, 413) |
|
192 |
self.assertEqual(user_vms_count(), 2) |
|
193 |
|
|
194 |
# admin wants test user to create 4 vms, now test user can create |
|
195 |
# one additional vm, but no more |
|
196 |
settings.VMS_USER_QUOTA = {'test':3} |
|
197 |
create_server() |
|
198 |
self.assertEqual(user_vms_count(), 3) |
|
199 |
resp = create_server() |
|
200 |
self.assertEqual(resp.status_code, 413) |
|
201 |
self.assertEqual(user_vms_count(), 3) |
|
202 |
# other users still apply to the global quota |
|
203 |
create_server("testuser2") |
|
204 |
self.assertEqual(user_vms_count("testuser2"), 1) |
|
205 |
resp = create_server("testuser2") |
|
206 |
self.assertEqual(resp.status_code, 413) |
|
207 |
self.assertEqual(user_vms_count("testuser2"), 1) |
|
208 |
|
|
209 |
|
|
210 |
def test_networks_quota(self): |
|
211 |
|
|
212 |
def create_network(for_user='test'): |
|
213 |
request = json.dumps({'network': {'name': 'user %s network' % |
|
214 |
for_user}}) |
|
215 |
self.astakos_response_user = for_user |
|
216 |
return self.client.post('/api/v1.1/networks', request, |
|
217 |
content_type="application/json") |
|
218 |
|
|
219 |
def user_networks_count(user='test'): |
|
220 |
return Network.objects.filter(userid=user).count() |
|
221 |
|
|
222 |
settings.MAX_NETWORKS_PER_USER = 1 |
|
223 |
create_network() |
|
224 |
self.assertEqual(user_networks_count(),1) |
|
225 |
resp = create_network() |
|
226 |
self.assertEqual(resp.status_code, 413) |
|
227 |
self.assertEqual(user_networks_count(), 1) |
|
228 |
|
|
229 |
settings.NETWORKS_USER_QUOTA = {'test':2} |
|
230 |
create_network() |
|
231 |
self.assertEqual(user_networks_count(),2) |
|
232 |
resp = create_network() |
|
233 |
self.assertEqual(resp.status_code, 413) |
|
234 |
self.assertEqual(user_networks_count(), 2) |
|
235 |
|
|
236 |
create_network("testuser2") |
|
237 |
self.assertEqual(user_networks_count("testuser2"),1) |
|
238 |
resp = create_network("testuser2") |
|
239 |
self.assertEqual(resp.status_code, 413) |
|
240 |
self.assertEqual(user_networks_count("testuser2"), 1) |
|
241 |
|
|
242 |
settings.GANETI_MAX_LINK_NUMBER = 3 |
|
243 |
settings.NETWORKS_USER_QUOTA = {'test':10} |
|
244 |
resp = create_network() |
|
245 |
self.assertEqual(Network.objects.count(), 4) |
|
246 |
self.assertEqual('No networks available.' in resp.content, True) |
|
247 |
self.assertEqual(user_networks_count(), 2) |
|
248 |
|
|
249 |
|
|
250 |
|
|
251 |
|
|
252 |
class APITestCase(TestCase): |
|
253 |
fixtures = ['users', 'api_test_data'] |
|
254 |
test_server_id = 1001 |
|
255 |
test_image_id = 1 |
|
256 |
test_flavor_id = 1 |
|
257 |
test_group_id = 1 |
|
258 |
test_wrong_server_id = 99999999 |
|
259 |
test_wrong_image_id = 99999999 |
|
260 |
test_wrong_flavor_id = 99999999 |
|
261 |
test_wrong_group_id = 99999999 |
|
262 |
#make the testing with these id's |
|
263 | 91 |
|
264 |
def setUp(self): |
|
265 |
self.client = AaiClient() |
|
266 |
settings.MAX_VMS_PER_USER = 5 |
|
92 |
class APITest(TestCase): |
|
267 | 93 |
|
268 | 94 |
def test_api_version(self): |
269 | 95 |
"""Check API version.""" |
270 |
|
|
271 |
response = self.client.get('/api/v1.1/') |
|
96 |
with astakos_user('user'): |
|
97 |
response = self.client.get('/api/v1.1/')
|
|
272 | 98 |
self.assertEqual(response.status_code, 200) |
273 | 99 |
api_version = json.loads(response.content)['version'] |
274 | 100 |
self.assertEqual(api_version['id'], 'v1.1') |
275 | 101 |
self.assertEqual(api_version['status'], 'CURRENT') |
276 | 102 |
|
277 |
def test_server_list(self): |
|
278 |
"""Test if the expected list of servers is returned.""" |
|
279 |
|
|
280 |
response = self.client.get('/api/v1.1/servers') |
|
281 |
vms_from_api = json.loads(response.content)['servers']['values'] |
|
282 |
vms_from_db = VirtualMachine.objects.filter(deleted=False) |
|
283 |
self.assertEqual(len(vms_from_api), len(vms_from_db)) |
|
284 |
self.assertTrue(response.status_code in [200, 203]) |
|
285 |
for vm_from_api in vms_from_api: |
|
286 |
vm_from_db = VirtualMachine.objects.get(id=vm_from_api['id']) |
|
287 |
self.assertEqual(vm_from_api['id'], vm_from_db.id) |
|
288 |
self.assertEqual(vm_from_api['name'], vm_from_db.name) |
|
289 |
|
|
290 |
def test_server_details(self): |
|
291 |
"""Test if the expected server is returned.""" |
|
292 |
|
|
293 |
response = self.client.get('/api/v1.1/servers/%d' % self.test_server_id) |
|
294 |
vm_from_api = json.loads(response.content)['server'] |
|
295 |
vm_from_db = VirtualMachine.objects.get(id=self.test_server_id) |
|
296 |
self.assertEqual(vm_from_api['flavorRef'], vm_from_db.flavor.id) |
|
297 |
self.assertEqual(vm_from_api['hostId'], vm_from_db.hostid) |
|
298 |
self.assertEqual(vm_from_api['id'], vm_from_db.id) |
|
299 |
self.assertEqual(vm_from_api['imageRef'], vm_from_db.imageid) |
|
300 |
self.assertEqual(vm_from_api['name'], vm_from_db.name) |
|
301 |
self.assertEqual(vm_from_api['status'], get_rsapi_state(vm_from_db)) |
|
302 |
self.assertTrue(response.status_code in [200, 203]) |
|
303 | 103 |
|
304 |
def test_servers_details(self): |
|
305 |
"""Test if the servers details are returned.""" |
|
306 |
|
|
307 |
response = self.client.get('/api/v1.1/servers/detail') |
|
308 |
|
|
309 |
# Make sure both DB and API responses are sorted by id, |
|
310 |
# to allow for 1-1 comparisons |
|
311 |
vms_from_db = VirtualMachine.objects.filter(deleted=False).order_by('id') |
|
312 |
vms_from_api = json.loads(response.content)['servers']['values'] |
|
313 |
vms_from_api = sorted(vms_from_api, key=lambda vm: vm['id']) |
|
314 |
self.assertEqual(len(vms_from_db), len(vms_from_api)) |
|
315 |
|
|
316 |
id_list = [vm.id for vm in vms_from_db] |
|
317 |
number = 0 |
|
318 |
for vm_id in id_list: |
|
319 |
vm_from_api = vms_from_api[number] |
|
320 |
vm_from_db = VirtualMachine.objects.get(id=vm_id) |
|
321 |
self.assertEqual(vm_from_api['flavorRef'], vm_from_db.flavor.id) |
|
322 |
self.assertEqual(vm_from_api['hostId'], vm_from_db.hostid) |
|
323 |
self.assertEqual(vm_from_api['id'], vm_from_db.id) |
|
324 |
self.assertEqual(vm_from_api['imageRef'], vm_from_db.imageid) |
|
325 |
self.assertEqual(vm_from_api['name'], vm_from_db.name) |
|
326 |
self.assertEqual(vm_from_api['status'], get_rsapi_state(vm_from_db)) |
|
327 |
number += 1 |
|
328 |
for vm_from_api in vms_from_api: |
|
329 |
vm_from_db = VirtualMachine.objects.get(id=vm_from_api['id']) |
|
330 |
self.assertEqual(vm_from_api['flavorRef'], vm_from_db.flavor.id) |
|
331 |
self.assertEqual(vm_from_api['hostId'], vm_from_db.hostid) |
|
332 |
self.assertEqual(vm_from_api['id'], vm_from_db.id) |
|
333 |
self.assertEqual(vm_from_api['imageRef'], vm_from_db.imageid) |
|
334 |
self.assertEqual(vm_from_api['name'], vm_from_db.name) |
|
335 |
self.assertEqual(vm_from_api['status'], get_rsapi_state(vm_from_db)) |
|
104 |
class BaseTestCase(TestCase): |
|
105 |
def get(self, url, user='user'): |
|
106 |
with astakos_user(user): |
|
107 |
response = self.client.get(url) |
|
108 |
return response |
|
109 |
|
|
110 |
def delete(self, url, user='user'): |
|
111 |
with astakos_user(user): |
|
112 |
response = self.client.delete(url) |
|
113 |
return response |
|
114 |
|
|
115 |
def post(self, url, user='user', params={}, ctype='json'): |
|
116 |
if ctype == 'json': |
|
117 |
content_type = 'application/json' |
|
118 |
with astakos_user(user): |
|
119 |
response = self.client.post(url, params, content_type=content_type) |
|
120 |
return response |
|
121 |
|
|
122 |
def put(self, url, user='user', params={}, ctype='json'): |
|
123 |
if ctype == 'json': |
|
124 |
content_type = 'application/json' |
|
125 |
with astakos_user(user): |
|
126 |
response = self.client.put(url, params, content_type=content_type) |
|
127 |
return response |
|
128 |
|
|
129 |
def assertSuccess(self, response): |
|
336 | 130 |
self.assertTrue(response.status_code in [200, 203]) |
337 | 131 |
|
338 |
def test_wrong_server(self): |
|
339 |
"""Test 404 response if server does not exist.""" |
|
340 |
|
|
341 |
response = self.client.get('/api/v1.1/servers/%d' % self.test_wrong_server_id) |
|
342 |
self.assertEqual(response.status_code, 404) |
|
343 |
|
|
344 |
def test_create_server_empty(self): |
|
345 |
"""Test if the create server call returns a 400 badRequest if |
|
346 |
no attributes are specified.""" |
|
347 |
|
|
348 |
response = self.client.post('/api/v1.1/servers', {}) |
|
349 |
self.assertEqual(response.status_code, 400) |
|
350 |
|
|
351 |
def test_create_server(self): |
|
352 |
"""Test if the create server call returns the expected response |
|
353 |
if a valid request has been speficied.""" |
|
354 |
|
|
355 |
request = { |
|
356 |
"server": { |
|
357 |
"name": "new-server-test", |
|
358 |
"userid": "test", |
|
359 |
"imageRef": 1, |
|
360 |
"flavorRef": 1, |
|
361 |
"metadata": { |
|
362 |
"My Server Name": "Apache1" |
|
363 |
}, |
|
364 |
"personality": [] |
|
365 |
} |
|
366 |
} |
|
367 |
response = self.client.post('/api/v1.1/servers', json.dumps(request), |
|
368 |
content_type='application/json') |
|
369 |
self.assertEqual(response.status_code, 202) |
|
370 |
#TODO: check response.content |
|
371 |
#TODO: check create server with wrong options (eg non existing flavor) |
|
372 |
|
|
373 |
def test_server_polling(self): |
|
374 |
"""Test if the server polling works as expected.""" |
|
375 |
|
|
376 |
response = self.client.get('/api/v1.1/servers/detail') |
|
377 |
vms_from_api_initial = json.loads(response.content)['servers']['values'] |
|
378 |
ts = mktime(parsedate(response['Date'])) |
|
379 |
since = datetime.datetime.fromtimestamp(ts).isoformat() + 'Z' |
|
380 |
response = self.client.get('/api/v1.1/servers/detail?changes-since=%s' % since) |
|
381 |
self.assertEqual(len(response.content), 0) |
|
382 |
|
|
383 |
#now create a machine. Then check if it is on the list |
|
384 |
request = { |
|
385 |
"server": { |
|
386 |
"name": "new-server-test", |
|
387 |
"imageRef": 1, |
|
388 |
"flavorRef": 1, |
|
389 |
"metadata": { |
|
390 |
"My Server Name": "Apache1" |
|
391 |
}, |
|
392 |
"personality": [] |
|
393 |
} |
|
394 |
} |
|
395 |
|
|
396 |
path = '/api/v1.1/servers' |
|
397 |
response = self.client.post(path, json.dumps(request), content_type='application/json') |
|
398 |
self.assertEqual(response.status_code, 202) |
|
399 |
|
|
400 |
response = self.client.get('/api/v1.1/servers/detail?changes-since=%s' % since) |
|
401 |
self.assertEqual(response.status_code, 200) |
|
402 |
vms_from_api_after = json.loads(response.content)['servers']['values'] |
|
403 |
#make sure the newly created server is included on the updated list |
|
404 |
self.assertEqual(len(vms_from_api_after), 1) |
|
405 |
|
|
406 |
def test_reboot_server(self): |
|
407 |
"""Test if the specified server is rebooted.""" |
|
408 |
request = {'reboot': {'type': 'HARD'}} |
|
409 |
path = '/api/v1.1/servers/%d/action' % self.test_server_id |
|
410 |
response = self.client.post(path, json.dumps(request), content_type='application/json') |
|
411 |
self.assertEqual(response.status_code, 202) |
|
412 |
# server id that does not exist |
|
413 |
path = '/api/v1.1/servers/%d/action' % self.test_wrong_server_id |
|
414 |
response = self.client.post(path, json.dumps(request), content_type='application/json') |
|
415 |
self.assertEqual(response.status_code, 404) |
|
132 |
def assertFault(self, response, status_code, name): |
|
133 |
self.assertEqual(response.status_code, status_code) |
|
134 |
fault = json.loads(response.content) |
|
135 |
self.assertEqual(fault.keys(), [name]) |
|
416 | 136 |
|
417 |
def test_shutdown_server(self):
|
|
418 |
"""Test if the specified server is shutdown."""
|
|
137 |
def assertBadRequest(self, response):
|
|
138 |
self.assertFault(response, 400, 'badRequest')
|
|
419 | 139 |
|
420 |
request = {'shutdown': {}} |
|
421 |
path = '/api/v1.1/servers/%d/action' % self.test_server_id |
|
422 |
response = self.client.post(path, json.dumps(request), content_type='application/json') |
|
423 |
self.assertEqual(response.status_code, 202) |
|
424 |
# server id that does not exist |
|
425 |
path = '/api/v1.1/servers/%d/action' % self.test_wrong_server_id |
|
426 |
response = self.client.post(path, json.dumps(request), content_type='application/json') |
|
427 |
self.assertEqual(response.status_code, 404) |
|
140 |
def assertItemNotFound(self, response): |
|
141 |
self.assertFault(response, 404, 'itemNotFound') |
|
428 | 142 |
|
429 |
def test_start_server(self): |
|
430 |
"""Test if the specified server is started.""" |
|
431 | 143 |
|
432 |
request = {'start': {}} |
|
433 |
path = '/api/v1.1/servers/%d/action' % self.test_server_id |
|
434 |
response = self.client.post(path, json.dumps(request), content_type='application/json') |
|
435 |
self.assertEqual(response.status_code, 202) |
|
436 |
# server id that does not exist |
|
437 |
path = '/api/v1.1/servers/%d/action' % self.test_wrong_server_id |
|
438 |
response = self.client.post(path, json.dumps(request), content_type='application/json') |
|
439 |
self.assertEqual(response.status_code, 404) |
|
144 |
class FlavorAPITest(BaseTestCase): |
|
440 | 145 |
|
441 |
def test_delete_server(self): |
|
442 |
"""Test if the specified server is deleted.""" |
|
443 |
response = self.client.delete('/api/v1.1/servers/%d' % self.test_server_id) |
|
444 |
self.assertEqual(response.status_code, 204) |
|
445 |
# server id that does not exist |
|
446 |
response = self.client.delete('/api/v1.1/servers/%d' % self.test_wrong_server_id) |
|
447 |
self.assertEqual(response.status_code, 404) |
|
146 |
def setUp(self): |
|
147 |
self.flavor1 = mfactory.FlavorFactory() |
|
148 |
self.flavor2 = mfactory.FlavorFactory(deleted=True) |
|
149 |
self.flavor3 = mfactory.FlavorFactory() |
|
448 | 150 |
|
449 | 151 |
def test_flavor_list(self): |
450 | 152 |
"""Test if the expected list of flavors is returned by.""" |
451 | 153 |
|
452 |
response = self.client.get('/api/v1.1/flavors') |
|
154 |
# with astakos_user('user'): |
|
155 |
# response = self.client.get('/api/v1.1/flavors') |
|
156 |
response = self.get('/api/v1.1/flavors') |
|
157 |
|
|
453 | 158 |
flavors_from_api = json.loads(response.content)['flavors']['values'] |
454 |
flavors_from_db = Flavor.objects.all()
|
|
159 |
flavors_from_db = Flavor.objects.filter(deleted=False)
|
|
455 | 160 |
self.assertEqual(len(flavors_from_api), len(flavors_from_db)) |
456 | 161 |
self.assertTrue(response.status_code in [200, 203]) |
457 | 162 |
for flavor_from_api in flavors_from_api: |
... | ... | |
461 | 166 |
|
462 | 167 |
def test_flavors_details(self): |
463 | 168 |
"""Test if the flavors details are returned.""" |
169 |
response = self.get('/api/v1.1/flavors/detail') |
|
464 | 170 |
|
465 |
response = self.client.get('/api/v1.1/flavors/detail') |
|
466 |
flavors_from_db = Flavor.objects.all() |
|
171 |
flavors_from_db = Flavor.objects.filter(deleted=False) |
|
467 | 172 |
flavors_from_api = json.loads(response.content)['flavors']['values'] |
468 | 173 |
|
469 | 174 |
# Assert that all flavors in the db appear inthe API call result |
... | ... | |
490 | 195 |
|
491 | 196 |
def test_flavor_details(self): |
492 | 197 |
"""Test if the expected flavor is returned.""" |
198 |
flavor = self.flavor3 |
|
199 |
|
|
200 |
response = self.get('/api/v1.1/flavors/%d' % flavor.id) |
|
493 | 201 |
|
494 |
response = self.client.get('/api/v1.1/flavors/%d' % self.test_flavor_id) |
|
495 | 202 |
flavor_from_api = json.loads(response.content)['flavor'] |
496 |
flavor_from_db = Flavor.objects.get(id=self.test_flavor_id)
|
|
203 |
flavor_from_db = Flavor.objects.get(id=flavor.id)
|
|
497 | 204 |
self.assertEqual(flavor_from_api['cpu'], flavor_from_db.cpu) |
498 | 205 |
self.assertEqual(flavor_from_api['id'], flavor_from_db.id) |
499 | 206 |
self.assertEqual(flavor_from_api['disk'], flavor_from_db.disk) |
... | ... | |
501 | 208 |
self.assertEqual(flavor_from_api['ram'], flavor_from_db.ram) |
502 | 209 |
self.assertTrue(response.status_code in [200, 203]) |
503 | 210 |
|
211 |
def test_deleted_flavor_details(self): |
|
212 |
"""Test that API returns details for deleted flavors""" |
|
213 |
flavor = self.flavor2 |
|
214 |
response = self.get('/api/v1.1/flavors/%d' % flavor.id) |
|
215 |
flavor_from_api = json.loads(response.content)['flavor'] |
|
216 |
self.assertEqual(response.status_code, 200) |
|
217 |
self.assertEquals(flavor_from_api['name'], flavor.name) |
|
218 |
|
|
219 |
def test_deleted_flavors_list(self): |
|
220 |
"""Test that deleted flavors do not appear to flavors list""" |
|
221 |
response = self.get('/api/v1.1/flavors') |
|
222 |
flavors_from_api = json.loads(response.content)['flavors']['values'] |
|
223 |
self.assertEqual(len(flavors_from_api), 2) |
|
224 |
|
|
225 |
def test_deleted_flavors_details(self): |
|
226 |
"""Test that deleted flavors do not appear to flavors detail list""" |
|
227 |
mfactory.FlavorFactory(deleted=True) |
|
228 |
response = self.get('/api/v1.1/flavors/detail') |
|
229 |
flavors_from_api = json.loads(response.content)['flavors']['values'] |
|
230 |
self.assertEqual(len(flavors_from_api), 2) |
|
231 |
|
|
504 | 232 |
def test_wrong_flavor(self): |
505 | 233 |
"""Test 404 result when requesting a flavor that does not exist.""" |
506 | 234 |
|
507 |
response = self.client.get('/api/v1.1/flavors/%d' % self.test_wrong_flavor_id)
|
|
508 |
self.assertTrue(response.status_code in [404, 503])
|
|
235 |
response = self.get('/api/v1.1/flavors/%d' % 22)
|
|
236 |
self.assertTrue(response.status_code in [404]) |
|
509 | 237 |
|
510 |
def test_image_list(self): |
|
511 |
"""Test if the expected list of images is returned by the API.""" |
|
512 | 238 |
|
513 |
response = self.client.get('/api/v1.1/images') |
|
514 |
images_from_api = json.loads(response.content)['images']['values'] |
|
515 |
images_from_db = Image.objects.all() |
|
516 |
self.assertEqual(len(images_from_api), len(images_from_db)) |
|
239 |
class ServerAPITest(BaseTestCase): |
|
240 |
def setUp(self): |
|
241 |
self.user1 = 'user1' |
|
242 |
self.user2 = 'user2' |
|
243 |
self.vm1 = mfactory.VirtualMachineFactory(userid=self.user1) |
|
244 |
self.vm2 = mfactory.VirtualMachineFactory(userid=self.user2) |
|
245 |
self.vm3 = mfactory.VirtualMachineFactory(deleted=True, |
|
246 |
userid=self.user1) |
|
247 |
self.vm4 = mfactory.VirtualMachineFactory(userid=self.user2) |
|
248 |
|
|
249 |
def test_server_list_1(self): |
|
250 |
"""Test if the expected list of servers is returned.""" |
|
251 |
response = self.get('/api/v1.1/servers') |
|
517 | 252 |
self.assertTrue(response.status_code in [200, 203]) |
518 |
for image_from_api in images_from_api: |
|
519 |
image_from_db = Image.objects.get(id=image_from_api['id']) |
|
520 |
self.assertEqual(image_from_api['id'], image_from_db.id) |
|
521 |
self.assertEqual(image_from_api['name'], image_from_db.name) |
|
253 |
servers = json.loads(response.content)['servers']['values'] |
|
254 |
self.assertEqual(servers, []) |
|
522 | 255 |
|
523 |
def test_wrong_image(self): |
|
524 |
"""Test 404 result if a non existent image is requested.""" |
|
256 |
def test_server_list_2(self): |
|
257 |
"""Test if the expected list of servers is returned.""" |
|
258 |
response = self.get('/api/v1.1/servers', self.user1) |
|
259 |
self.assertTrue(response.status_code in [200, 203]) |
|
260 |
servers = json.loads(response.content)['servers']['values'] |
|
261 |
db_server = self.vm1 |
|
262 |
self.assertEqual(servers, [{'name': db_server.name, |
|
263 |
'id': db_server.id}]) |
|
264 |
|
|
265 |
def test_server_list_detail(self): |
|
266 |
"""Test if the servers list details are returned.""" |
|
267 |
user = self.user2 |
|
268 |
user_vms = {self.vm2.id: self.vm2, |
|
269 |
self.vm4.id: self.vm4} |
|
270 |
|
|
271 |
response = self.get('/api/v1.1/servers/detail', user) |
|
272 |
servers = json.loads(response.content)['servers']['values'] |
|
273 |
self.assertEqual(len(servers), len(user_vms)) |
|
274 |
for api_vm in servers: |
|
275 |
db_vm = user_vms[api_vm['id']] |
|
276 |
self.assertEqual(api_vm['flavorRef'], db_vm.flavor.id) |
|
277 |
self.assertEqual(api_vm['hostId'], db_vm.hostid) |
|
278 |
self.assertEqual(api_vm['id'], db_vm.id) |
|
279 |
self.assertEqual(api_vm['imageRef'], db_vm.imageid) |
|
280 |
self.assertEqual(api_vm['name'], db_vm.name) |
|
281 |
self.assertEqual(api_vm['status'], get_rsapi_state(db_vm)) |
|
282 |
self.assertTrue(response.status_code in [200, 203]) |
|
283 |
|
|
284 |
def test_server_detail(self): |
|
285 |
"""Test if a server details are returned.""" |
|
286 |
db_vm = self.vm2 |
|
287 |
user = self.vm2.userid |
|
288 |
db_vm_meta = mfactory.VirtualMachineMetadataFactory(vm=db_vm) |
|
289 |
|
|
290 |
response = self.get('/api/v1.1/servers/%d' % db_vm.id, user) |
|
291 |
server = json.loads(response.content)['server'] |
|
292 |
|
|
293 |
self.assertEqual(server['flavorRef'], db_vm.flavor.id) |
|
294 |
self.assertEqual(server['hostId'], db_vm.hostid) |
|
295 |
self.assertEqual(server['id'], db_vm.id) |
|
296 |
self.assertEqual(server['imageRef'], db_vm.imageid) |
|
297 |
self.assertEqual(server['name'], db_vm.name) |
|
298 |
self.assertEqual(server['status'], get_rsapi_state(db_vm)) |
|
299 |
|
|
300 |
metadata = server['metadata']['values'] |
|
301 |
self.assertEqual(len(metadata), 1) |
|
302 |
self.assertEqual(metadata[db_vm_meta.meta_key], db_vm_meta.meta_value) |
|
303 |
self.assertTrue(response.status_code in [200, 203]) |
|
304 |
|
|
305 |
def test_noauthorized(self): |
|
306 |
"""Test 404 for detail of other user vm""" |
|
307 |
db_vm = self.vm2 |
|
525 | 308 |
|
526 |
response = self.client.get('/api/v1.1/images/%d' % self.test_wrong_image_id)
|
|
309 |
response = self.get('/api/v1.1/servers/%d' % db_vm.id, 'wrong_user')
|
|
527 | 310 |
self.assertEqual(response.status_code, 404) |
528 | 311 |
|
529 |
def test_server_metadata(self): |
|
530 |
"""Test server's metadata (add, edit).""" |
|
312 |
def test_wrong_server(self): |
|
313 |
"""Test 404 response if server does not exist.""" |
|
314 |
response = self.get('/api/v1.1/servers/%d' % 5000) |
|
315 |
self.assertEqual(response.status_code, 404) |
|
531 | 316 |
|
532 |
key = 'name' |
|
533 |
request = {'meta': {key: 'a fancy name'}} |
|
317 |
def test_create_server_empty(self): |
|
318 |
"""Test if the create server call returns a 400 badRequest if |
|
319 |
no attributes are specified.""" |
|
534 | 320 |
|
535 |
path = '/api/v1.1/servers/%d/meta/%s' % (self.test_server_id, key) |
|
536 |
response = self.client.put(path, json.dumps(request), content_type='application/json') |
|
537 |
self.assertEqual(response.status_code, 201) |
|
321 |
response = self.post('/api/v1.1/servers', params={}) |
|
322 |
self.assertEqual(response.status_code, 400) |
|
538 | 323 |
|
539 | 324 |
|
540 |
def create_flavors(n=1): |
|
541 |
for i in range(n): |
|
542 |
Flavor.objects.create( |
|
543 |
cpu=randint(1, 4), |
|
544 |
ram=randint(1, 8) * 512, |
|
545 |
disk=randint(1, 40)) |
|
325 |
@patch('synnefo.api.util.get_image') |
|
326 |
@patch('synnefo.logic.rapi_pool.GanetiRapiClient') |
|
327 |
class ServerCreateAPITest(BaseTestCase): |
|
328 |
def test_create_server(self, mrapi, mimage): |
|
329 |
"""Test if the create server call returns the expected response |
|
330 |
if a valid request has been speficied.""" |
|
331 |
mimage.return_value = {'location': 'pithos://foo', |
|
332 |
'disk_format': 'diskdump'} |
|
333 |
mrapi().CreateInstance.return_value = 12 |
|
334 |
flavor = mfactory.FlavorFactory() |
|
335 |
# Create public network and backend |
|
336 |
network = mfactory.NetworkFactory(public=True) |
|
337 |
backend = mfactory.BackendFactory() |
|
338 |
mfactory.BackendNetworkFactory(network=network, backend=backend) |
|
546 | 339 |
|
340 |
request = { |
|
341 |
"server": { |
|
342 |
"name": "new-server-test", |
|
343 |
"userid": "test_user", |
|
344 |
"imageRef": 1, |
|
345 |
"flavorRef": flavor.id, |
|
346 |
"metadata": { |
|
347 |
"My Server Name": "Apache1" |
|
348 |
}, |
|
349 |
"personality": [] |
|
350 |
} |
|
351 |
} |
|
352 |
response = self.post('/api/v1.1/servers', 'test_user', |
|
353 |
json.dumps(request), 'json') |
|
354 |
self.assertEqual(response.status_code, 202) |
|
355 |
mrapi().CreateInstance.assert_called_once() |
|
547 | 356 |
|
548 |
def create_images(n=1):
|
|
549 |
for i in range(n):
|
|
550 |
Image.objects.create(
|
|
551 |
name='Image %d' % (i + 1),
|
|
552 |
state='ACTIVE',
|
|
553 |
owner='test')
|
|
357 |
api_server = json.loads(response.content)['server']
|
|
358 |
self.assertEqual(api_server['status'], "BUILD")
|
|
359 |
self.assertEqual(api_server['progress'], 0)
|
|
360 |
self.assertEqual(api_server['metadata']['values'],
|
|
361 |
{"My Server Name": "Apache1"})
|
|
362 |
self.assertTrue('adminPass' in api_server)
|
|
554 | 363 |
|
364 |
db_vm = VirtualMachine.objects.get(userid='test_user') |
|
365 |
self.assertEqual(api_server['name'], db_vm.name) |
|
366 |
self.assertEqual(api_server['status'], db_vm.operstate) |
|
555 | 367 |
|
556 |
def create_image_metadata(n=1): |
|
557 |
images = Image.objects.all() |
|
558 |
for i in range(n): |
|
559 |
ImageMetadata.objects.create( |
|
560 |
meta_key='Key%d' % (i + 1), |
|
561 |
meta_value='Value %d' % (i + 1), |
|
562 |
image=choice(images)) |
|
368 |
def test_create_server_no_flavor(self, mrapi, mimage): |
|
369 |
request = { |
|
370 |
"server": { |
|
371 |
"name": "new-server-test", |
|
372 |
"userid": "test_user", |
|
373 |
"imageRef": 1, |
|
374 |
"flavorRef": 42, |
|
375 |
"metadata": { |
|
376 |
"My Server Name": "Apache1" |
|
377 |
}, |
|
378 |
"personality": [] |
|
379 |
} |
|
380 |
} |
|
381 |
response = self.post('/api/v1.1/servers', 'test_user', |
|
382 |
json.dumps(request), 'json') |
|
383 |
self.assertItemNotFound(response) |
|
563 | 384 |
|
564 | 385 |
|
565 |
def create_servers(n=1): |
|
566 |
flavors = Flavor.objects.all() |
|
567 |
images = Image.objects.all() |
|
568 |
for i in range(n): |
|
569 |
VirtualMachine.objects.create( |
|
570 |
name='Server %d' % (i + 1), |
|
571 |
owner='test', |
|
572 |
imageid=choice(images).id, |
|
573 |
hostid=str(i), |
|
574 |
flavor=choice(flavors)) |
|
386 |
@patch('synnefo.logic.rapi_pool.GanetiRapiClient') |
|
387 |
class ServerDestroyAPITest(BaseTestCase): |
|
388 |
def test_delete_server(self, mrapi): |
|
389 |
vm = mfactory.VirtualMachineFactory() |
|
390 |
response = self.delete('/api/v1.1/servers/%d' % vm.id, vm.userid) |
|
391 |
self.assertEqual(response.status_code, 204) |
|
392 |
mrapi().DeleteInstance.assert_called_once() |
|
393 |
|
|
394 |
def test_non_existing_delete_server(self, mrapi): |
|
395 |
vm = mfactory.VirtualMachineFactory() |
|
396 |
response = self.delete('/api/v1.1/servers/%d' % 42, vm.userid) |
|
397 |
self.assertItemNotFound(response) |
|
398 |
mrapi().DeleteInstance.assert_not_called() |
|
399 |
|
|
400 |
|
|
401 |
@patch('synnefo.api.util.get_image') |
|
402 |
@patch('synnefo.logic.rapi_pool.GanetiRapiClient') |
|
403 |
class ServerActionAPITest(BaseTestCase): |
|
404 |
def test_actions(self, mrapi, mimage): |
|
405 |
actions = ['start', 'shutdown', 'reboot'] |
|
406 |
vm = mfactory.VirtualMachineFactory() |
|
407 |
vm.operstate = "STOPPED" |
|
408 |
vm.save() |
|
409 |
for action in actions: |
|
410 |
val = {'type': 'HARD'} if action == 'reboot' else {} |
|
411 |
request = {action: val} |
|
412 |
response = self.post('/api/v1.1/servers/%d/action' % vm.id, |
|
413 |
vm.userid, json.dumps(request), 'json') |
|
414 |
self.assertEqual(response.status_code, 202) |
|
415 |
if action == 'shutdown': |
|
416 |
self.assertEqual(VirtualMachine.objects.get(id=vm.id).action, |
|
417 |
"STOP") |
|
418 |
else: |
|
419 |
self.assertEqual(VirtualMachine.objects.get(id=vm.id).action, |
|
420 |
action.upper()) |
|
421 |
|
|
422 |
def test_firewall(self, mrapi, mimage): |
|
423 |
vm = mfactory.VirtualMachineFactory() |
|
424 |
vm.operstate = "STOPPED" |
|
425 |
vm.save() |
|
426 |
request = {'firewallProfile': {'profile': 'PROTECTED'}} |
|
427 |
response = self.post('/api/v1.1/servers/%d/action' % vm.id, |
|
428 |
vm.userid, json.dumps(request), 'json') |
|
429 |
self.assertEqual(response.status_code, 202) |
|
430 |
mrapi().ModifyInstance.assert_called_once() |
|
575 | 431 |
|
576 | 432 |
|
577 |
def create_server_metadata(n=1): |
|
578 |
servers = VirtualMachine.objects.all() |
|
579 |
for i in range(n): |
|
580 |
VirtualMachineMetadata.objects.create( |
|
581 |
meta_key='Key%d' % (i + 1), |
|
582 |
meta_value='Value %d' % (i + 1), |
|
583 |
vm=choice(servers)) |
|
433 |
class ServerMetadataAPITest(BaseTestCase): |
|
434 |
def setUp(self): |
|
435 |
self.vm = mfactory.VirtualMachineFactory() |
|
436 |
self.metadata = mfactory.VirtualMachineMetadataFactory(vm=self.vm) |
|
437 |
|
|
438 |
def test_get_metadata(self): |
|
439 |
vm = self.vm |
|
440 |
create_meta = lambda: mfactory.VirtualMachineMetadataFactory(vm=vm) |
|
441 |
metadata = [create_meta(), create_meta(), create_meta()] |
|
442 |
response = self.get('/api/v1.1/servers/%d/meta' % vm.id, vm.userid) |
|
443 |
self.assertTrue(response.status_code in [200, 203]) |
|
444 |
api_metadata = json.loads(response.content)['metadata']['values'] |
|
445 |
self.assertEqual(len(api_metadata), len(metadata) + 1) |
|
446 |
for db_m in metadata: |
|
447 |
self.assertEqual(api_metadata[db_m.meta_key], db_m.meta_value) |
|
448 |
|
|
449 |
request = {'metadata': |
|
450 |
{'foo': 'bar'}, |
|
451 |
metadata[0].meta_key: 'bar2' |
|
452 |
} |
|
453 |
response = self.post('/api/v1.1/servers/%d/meta' % vm.id, vm.userid, |
|
454 |
json.dumps(request), 'json') |
|
455 |
metadata2 = VirtualMachineMetadata.objects.filter(vm=vm) |
|
456 |
response = self.get('/api/v1.1/servers/%d/meta' % vm.id, vm.userid) |
|
457 |
self.assertTrue(response.status_code in [200, 203]) |
|
458 |
api_metadata2 = json.loads(response.content)['metadata']['values'] |
|
459 |
self.assertTrue('foo' in api_metadata2.keys()) |
|
460 |
self.assertTrue(api_metadata2[metadata[0].meta_key], 'bar2') |
|
461 |
self.assertEqual(len(api_metadata2), len(metadata2)) |
|
462 |
for db_m in metadata2: |
|
463 |
self.assertEqual(api_metadata2[db_m.meta_key], db_m.meta_value) |
|
464 |
|
|
465 |
# Create new meta |
|
466 |
request = {'meta': {'foo2': 'bar2'}} |
|
467 |
response = self.put('/api/v1.1/servers/%d/meta/foo2' % vm.id, |
|
468 |
vm.userid, json.dumps(request), 'json') |
|
469 |
|
|
470 |
# Get the new meta |
|
471 |
response = self.get('/api/v1.1/servers/%d/meta/foo2' % vm.id, |
|
472 |
vm.userid) |
|
473 |
meta = json.loads(response.content)['meta'] |
|
474 |
self.assertEqual(meta['foo2'], 'bar2') |
|
475 |
|
|
476 |
# Delete the new meta |
|
477 |
response = self.delete('/api/v1.1/servers/%d/meta/foo2' % vm.id, |
|
478 |
vm.userid) |
|
479 |
self.assertEqual(response.status_code, 204) |
|
584 | 480 |
|
481 |
# Try to get the deleted meta: should raise 404 |
|
482 |
response = self.get('/api/v1.1/servers/%d/meta/foo2' % vm.id, |
|
483 |
vm.userid) |
|
484 |
self.assertEqual(response.status_code, 404) |
|
585 | 485 |
|
586 |
class AssertInvariant(object):
|
|
587 |
def __init__(self, callable, *args, **kwargs):
|
|
588 |
self.callable = callable
|
|
589 |
self.args = args
|
|
590 |
self.kwargs = kwargs
|
|
486 |
def test_invalid_metadata(self):
|
|
487 |
vm = self.vm
|
|
488 |
response = self.post('/api/v1.1/servers/%d/meta' % vm.id, vm.userid)
|
|
489 |
self.assertBadRequest(response)
|
|
490 |
self.assertEqual(len(vm.metadata.all()), 1)
|
|
591 | 491 |
|
592 |
def __enter__(self):
|
|
593 |
self.value = self.callable(*self.args, **self.kwargs)
|
|
594 |
return self.value
|
|
492 |
def test_invalid_metadata_server(self):
|
|
493 |
response = self.post('/api/v1.1/servers/42/meta', 'user')
|
|
494 |
self.assertItemNotFound(response)
|
|
595 | 495 |
|
596 |
def __exit__(self, type, value, tb): |
|
597 |
assert self.value == self.callable(*self.args, **self.kwargs) |
|
496 |
def test_get_meta_invalid_key(self): |
|
497 |
vm = self.vm |
|
498 |
response = self.get('/api/v1.1/servers/%d/meta/foo2' % vm.id, |
|
499 |
vm.userid) |
|
500 |
self.assertItemNotFound(response) |
|
598 | 501 |
|
599 | 502 |
|
600 |
class BaseTestCase(TestCase): |
|
601 |
FLAVORS = 1 |
|
602 |
IMAGES = 1 |
|
603 |
SERVERS = 1 |
|
604 |
SERVER_METADATA = 0 |
|
605 |
IMAGE_METADATA = 0 |
|
606 |
fixtures = ['users'] |
|
607 |
|
|
503 |
@patch('synnefo.logic.rapi_pool.GanetiRapiClient') |
|
504 |
class NetworkAPITest(BaseTestCase): |
|
608 | 505 |
def setUp(self): |
609 |
self.client = AaiClient() |
|
610 |
create_flavors(self.FLAVORS) |
|
611 |
create_images(self.IMAGES) |
|
612 |
create_image_metadata(self.IMAGE_METADATA) |
|
613 |
create_servers(self.SERVERS) |
|
614 |
create_server_metadata(self.SERVER_METADATA) |
|
615 |
|
|
616 |
def assertFault(self, response, status_code, name): |
|
617 |
self.assertEqual(response.status_code, status_code) |
|
618 |
fault = json.loads(response.content) |
|
619 |
self.assertEqual(fault.keys(), [name]) |
|
620 |
|
|
621 |
def assertBadRequest(self, response): |
|
622 |
self.assertFault(response, 400, 'badRequest') |
|
623 |
|
|
624 |
def assertItemNotFound(self, response): |
|
625 |
self.assertFault(response, 404, 'itemNotFound') |
|
626 |
|
|
627 |
def list_images(self, detail=False): |
|
628 |
path = '/api/v1.1/images' |
|
506 |
self.mac_prefixes = mfactory.MacPrefixPoolTableFactory() |
|
507 |
self.bridges = mfactory.BridgePoolTableFactory() |
|
508 |
self.user = 'dummy-user' |
|
509 |
self.net1 = mfactory.NetworkFactory(userid=self.user) |
|
510 |
self.net2 = mfactory.NetworkFactory(userid=self.user) |
|
511 |
|
|
512 |
def assertNetworksEqual(self, db_net, api_net, detail=False): |
|
513 |
self.assertEqual(str(db_net.id), api_net["id"]) |
|
514 |
self.assertEqual(db_net.name, api_net['name']) |
|
629 | 515 |
if detail: |
630 |
path += '/detail' |
|
631 |
response = self.client.get(path) |
|
632 |
self.assertTrue(response.status_code in (200, 203)) |
|
633 |
reply = json.loads(response.content) |
|
634 |
self.assertEqual(reply.keys(), ['images']) |
|
635 |
self.assertEqual(reply['images'].keys(), ['values']) |
|
636 |
return reply['images']['values'] |
|
637 |
|
|
638 |
def list_metadata(self, path): |
|
639 |
response = self.client.get(path) |
|
640 |
self.assertTrue(response.status_code in (200, 203)) |
|
641 |
reply = json.loads(response.content) |
|
642 |
self.assertEqual(reply.keys(), ['metadata']) |
|
643 |
self.assertEqual(reply['metadata'].keys(), ['values']) |
|
644 |
return reply['metadata']['values'] |
|
645 |
|
|
646 |
def list_server_metadata(self, server_id): |
|
647 |
path = '/api/v1.1/servers/%d/meta' % server_id |
|
648 |
return self.list_metadata(path) |
|
649 |
|
|
650 |
def list_image_metadata(self, image_id): |
|
651 |
path = '/api/v1.1/images/%d/meta' % image_id |
|
652 |
return self.list_metadata(path) |
|
653 |
|
|
654 |
def update_metadata(self, path, metadata): |
|
655 |
data = json.dumps({'metadata': metadata}) |
|
656 |
response = self.client.post(path, data, content_type='application/json') |
|
657 |
self.assertEqual(response.status_code, 201) |
|
658 |
reply = json.loads(response.content) |
|
659 |
self.assertEqual(reply.keys(), ['metadata']) |
|
660 |
return reply['metadata'] |
|
661 |
|
|
662 |
def update_server_metadata(self, server_id, metadata): |
|
663 |
path = '/api/v1.1/servers/%d/meta' % server_id |
|
664 |
return self.update_metadata(path, metadata) |
|
665 |
|
|
666 |
def update_image_metadata(self, image_id, metadata): |
|
667 |
path = '/api/v1.1/images/%d/meta' % image_id |
|
668 |
return self.update_metadata(path, metadata) |
|
669 |
|
|
670 |
def create_server_meta(self, server_id, meta): |
|
671 |
key = meta.keys()[0] |
|
672 |
path = '/api/v1.1/servers/%d/meta/%s' % (server_id, key) |
|
673 |
data = json.dumps({'meta': meta}) |
|
674 |
response = self.client.put(path, data, content_type='application/json') |
|
675 |
self.assertEqual(response.status_code, 201) |
|
676 |
reply = json.loads(response.content) |
|
677 |
self.assertEqual(reply.keys(), ['meta']) |
|
678 |
response_meta = reply['meta'] |
|
679 |
self.assertEqual(response_meta, meta) |
|
680 |
|
|
681 |
def get_all_server_metadata(self): |
|
682 |
metadata = defaultdict(dict) |
|
683 |
for m in VirtualMachineMetadata.objects.all(): |
|
684 |
metadata[m.vm.id][m.meta_key] = m.meta_value |
|
685 |
return metadata |
|
686 |
|
|
687 |
def get_all_image_metadata(self): |
|
688 |
metadata = defaultdict(dict) |
|
689 |
for m in ImageMetadata.objects.all(): |
|
690 |
metadata[m.image.id][m.meta_key] = m.meta_value |
|
691 |
return metadata |
|
692 |
|
|
693 |
def list_networks(self, detail=False): |
|
694 |
path = '/api/v1.1/networks' |
|
695 |
if detail: |
|
696 |
path += '/detail' |
|
697 |
response = self.client.get(path) |
|
698 |
self.assertTrue(response.status_code in (200, 203)) |
|
699 |
reply = json.loads(response.content) |
|
700 |
self.assertEqual(reply.keys(), ['networks']) |
|
701 |
self.assertEqual(reply['networks'].keys(), ['values']) |
|
702 |
return reply['networks']['values'] |
|
703 |
|
|
704 |
def create_network(self, name): |
|
705 |
with astakos_user("admin@adminland.com"): |
|
706 |
path = '/api/v1.1/networks' |
|
707 |
data = json.dumps({'network': {'name': name}}) |
|
708 |
response = self.client.post(path, data, content_type='application/json') |
|
709 |
self.assertEqual(response.status_code, 202) |
|
710 |
reply = json.loads(response.content) |
|
711 |
self.assertEqual(reply.keys(), ['network']) |
|
712 |
return reply |
|
713 |
|
|
714 |
def get_network_details(self, network_id): |
|
715 |
path = '/api/v1.1/networks/%s' % network_id |
|
716 |
response = self.client.get(path) |
|
717 |
self.assertEqual(response.status_code, 200) |
|
718 |
reply = json.loads(response.content) |
|
719 |
self.assertEqual(reply.keys(), ['network']) |
|
720 |
return reply['network'] |
|
516 |
self.assertEqual(db_net.state, api_net['status']) |
|
517 |
self.assertEqual(db_net.flavor, api_net['type']) |
|
518 |
self.assertEqual(db_net.subnet, api_net['cidr']) |
|
519 |
self.assertEqual(db_net.subnet6, api_net['cidr6']) |
|
520 |
self.assertEqual(db_net.gateway, api_net['gateway']) |
|
521 |
self.assertEqual(db_net.gateway6, api_net['gateway6']) |
|
522 |
self.assertEqual(db_net.dhcp, api_net['dhcp']) |
|
523 |
|
|
524 |
def test_create_network_1(self, mrapi): |
|
525 |
request = { |
|
526 |
'network': {'name': 'foo'} |
|
527 |
} |
|
528 |
response = self.post('/api/v1.1/networks/', 'user1', |
|
529 |
json.dumps(request), 'json') |
|
530 |
self.assertEqual(response.status_code, 202) |
|
531 |
db_networks = Network.objects.filter(userid='user1') |
|
532 |
self.assertEqual(len(db_networks), 1) |
|
533 |
db_net = db_networks[0] |
|
534 |
api_net = json.loads(response.content)['network'] |
|
535 |
self.assertNetworksEqual(db_net, api_net) |
|
536 |
mrapi.CreateNetwork.assert_called() |
|
537 |
mrapi.ConnectNetwork.assert_called() |
|
538 |
|
|
539 |
def test_invalid_data_1(self, mrapi): |
|
540 |
"""Test invalid flavor""" |
|
541 |
request = { |
|
542 |
'network': {'name': 'foo', 'type': 'LoLo'} |
|
543 |
} |
|
544 |
response = self.post('/api/v1.1/networks/', 'user1', |
|
545 |
json.dumps(request), 'json') |
|
546 |
self.assertBadRequest(response) |
|
547 |
self.assertEqual(len(Network.objects.filter(userid='user1')), 0) |
|
721 | 548 |
|
722 |
def update_network_name(self, network_id, new_name): |
|
723 |
path = '/api/v1.1/networks/%s' % network_id |
|
724 |
data = json.dumps({'network': {'name': new_name}}) |
|
725 |
response = self.client.put(path, data, content_type='application/json') |
|
549 |
def test_invalid_data_2(self, mrapi): |
|
550 |
"""Test invalid subnet""" |
|
551 |
request = { |
|
552 |
'network': {'name': 'foo', 'cidr': '10.0.0.0/8'} |
|
553 |
} |
|
554 |
response = self.post('/api/v1.1/networks/', 'user1', |
|
555 |
json.dumps(request), 'json') |
|
556 |
self.assertFault(response, 413, "overLimit") |
|
557 |
|
|
558 |
def test_invalid_data_3(self, mrapi): |
|
559 |
"""Test unauthorized to create public network""" |
|
560 |
request = { |
|
561 |
'network': {'name': 'foo', 'public': True} |
|
562 |
} |
|
563 |
response = self.post('/api/v1.1/networks/', 'user1', |
|
564 |
json.dumps(request), 'json') |
|
565 |
self.assertFault(response, 403, "forbidden") |
|
566 |
|
|
567 |
def test_list_networks(self, mrapi): |
|
568 |
mfactory.NetworkFactory(userid=self.user, deleted=True) |
|
569 |
response = self.get('/api/v1.1/networks/', self.user) |
|
570 |
self.assertSuccess(response) |
|
571 |
db_nets = Network.objects.filter(userid=self.user, deleted=False) |
|
572 |
api_nets = json.loads(response.content)["networks"]["values"] |
|
573 |
self.assertEqual(len(db_nets), len(api_nets)) |
|
574 |
for api_net in api_nets: |
|
575 |
net_id = api_net['id'] |
|
576 |
self.assertNetworksEqual(Network.objects.get(id=net_id), api_net) |
|
577 |
|
|
578 |
def test_list_networks_detail(self, mrapi): |
|
579 |
mfactory.NetworkFactory(userid=self.user, deleted=True) |
|
580 |
response = self.get('/api/v1.1/networks/detail', self.user) |
|
581 |
self.assertSuccess(response) |
|
582 |
db_nets = Network.objects.filter(userid=self.user, deleted=False) |
|
583 |
api_nets = json.loads(response.content)["networks"]["values"] |
|
584 |
self.assertEqual(len(db_nets), len(api_nets)) |
|
585 |
for api_net in api_nets: |
|
586 |
net_id = api_net['id'] |
|
587 |
self.assertNetworksEqual(Network.objects.get(id=net_id), api_net, |
|
588 |
detail=True) |
|
589 |
|
|
590 |
def test_network_details_1(self, mrapi): |
|
591 |
response = self.get('/api/v1.1/networks/%d' % self.net1.id, |
|
592 |
self.net1.userid) |
|
593 |
self.assertSuccess(response) |
|
594 |
api_net = json.loads(response.content)["network"] |
|
595 |
self.assertNetworksEqual(self.net1, api_net, detail=True) |
|
596 |
|
|
597 |
def test_invalid_network(self, mrapi): |
|
598 |
response = self.get('/api/v1.1/networks/%d' % 42, |
|
599 |
self.net1.userid) |
|
600 |
self.assertItemNotFound(response) |
|
601 |
|
|
602 |
def test_rename_network(self, mrapi): |
|
603 |
request = {'network': {'name': "new_name"}} |
|
604 |
response = self.put('/api/v1.1/networks/%d' % self.net2.id, |
|
605 |
self.net2.userid, json.dumps(request), 'json') |
|
726 | 606 |
self.assertEqual(response.status_code, 204) |
727 |
|
|
728 |
def delete_network(self, network_id): |
|
729 |
path = '/api/v1.1/networks/%s' % network_id |
|
730 |
response = self.client.delete(path) |
|
607 |
self.assertEqual(Network.objects.get(id=self.net2.id).name, "new_name") |
|
608 |
|
|
609 |
def test_rename_public_network(self, mrapi): |
|
610 |
net = mfactory.NetworkFactory(public=True) |
|
611 |
request = {'network': {'name': "new_name"}} |
|
612 |
response = self.put('/api/v1.1/networks/%d' % net.id, |
|
613 |
self.net2.userid, json.dumps(request), 'json') |
|
614 |
self.assertFault(response, 403, 'forbidden') |
|
615 |
|
|
616 |
def test_delete_network(self, mrapi): |
|
617 |
response = self.delete('/api/v1.1/networks/%d' % self.net2.id, |
|
618 |
self.net2.userid) |
|
731 | 619 |
self.assertEqual(response.status_code, 204) |
732 |
|
|
733 |
def add_to_network(self, network_id, server_id): |
|
734 |
path = '/api/v1.1/networks/%s/action' % network_id |
|
735 |
data = json.dumps({'add': {'serverRef': server_id}}) |
|
736 |
response = self.client.post(path, data, content_type='application/json') |
|
620 |
net = Network.objects.get(id=self.net2.id, userid=self.net2.userid) |
|
621 |
self.assertEqual(net.action, 'DESTROY') |
|
622 |
mrapi.DeleteNetwork.assert_called() |
|
623 |
|
|
624 |
def test_delete_public_network(self, mrapi): |
|
625 |
net = mfactory.NetworkFactory(public=True) |
|
626 |
response = self.delete('/api/v1.1/networks/%d' % net.id, |
|
627 |
self.net2.userid) |
|
628 |
self.assertFault(response, 403, 'forbidden') |
|
629 |
mrapi.DeleteNetwork.assert_not_called() |
|
630 |
|
|
631 |
def test_add_nic(self, mrapi): |
|
632 |
user = 'userr' |
|
633 |
vm = mfactory.VirtualMachineFactory(name='yo', userid=user) |
|
634 |
net = mfactory.NetworkFactory(state='ACTIVE', userid=user) |
|
635 |
request = {'add': {'serverRef': vm.id}} |
|
636 |
response = self.post('/api/v1.1/networks/%d/action' % net.id, |
|
637 |
net.userid, json.dumps(request), 'json') |
|
737 | 638 |
self.assertEqual(response.status_code, 202) |
738 | 639 |
|
739 |
def remove_from_network(self, network_id, server_id): |
|
740 |
path = '/api/v1.1/networks/%s/action' % network_id |
|
741 |
data = json.dumps({'remove': {'serverRef': server_id}}) |
|
742 |
response = self.client.post(path, data, content_type='application/json') |
|
743 |
self.assertEqual(response.status_code, 202) |
|
744 |
|
|
745 |
|
|
746 |
def popdict(l, **kwargs): |
|
747 |
"""Pops a dict from list `l` based on the predicates given as `kwargs`.""" |
|
748 |
|
|
749 |
for i in range(len(l)): |
|
750 |
item = l[i] |
|
751 |
match = True |
|
752 |
for key, val in kwargs.items(): |
|
753 |
if item[key] != val: |
|
754 |
match = False |
|
755 |
break |
|
756 |
if match: |
|
757 |
del l[i] |
|
758 |
return item |
|
759 |
return None |
|
760 |
|
|
761 |
|
|
762 |
class ListImages(BaseTestCase): |
|
763 |
IMAGES = 10 |
|
764 |
|
|
765 |
def test_list_images(self): |
|
766 |
images = self.list_images() |
|
767 |
keys = set(['id', 'name']) |
|
768 |
for img in Image.objects.all(): |
|
769 |
image = popdict(images, id=img.id) |
|
770 |
self.assertTrue(image is not None) |
|
771 |
self.assertEqual(set(image.keys()), keys) |
|
772 |
self.assertEqual(image['id'], img.id) |
|
773 |
self.assertEqual(image['name'], img.name) |
|
774 |
self.assertEqual(images, []) |
|
775 |
|
|
776 |
def test_list_images_detail(self): |
|
777 |
images = self.list_images(detail=True) |
|
778 |
keys = set(['id', 'name', 'updated', 'created', 'status', 'progress']) |
|
779 |
for img in Image.objects.all(): |
|
780 |
image = popdict(images, id=img.id) |
|
781 |
self.assertTrue(image is not None) |
|
782 |
self.assertEqual(set(image.keys()), keys) |
|
783 |
self.assertEqual(image['id'], img.id) |
|
784 |
self.assertEqual(image['name'], img.name) |
|
785 |
self.assertEqual(image['status'], img.state) |
|
786 |
self.assertEqual(image['progress'], 100 if img.state == 'ACTIVE' else 0) |
|
787 |
self.assertEqual(images, []) |
|
788 |
|
|
789 |
|
|
790 |
class ListServerMetadata(BaseTestCase): |
|
791 |
SERVERS = 5 |
|
792 |
SERVER_METADATA = 100 |
|
793 |
|
|
794 |
def test_list_metadata(self): |
|
795 |
with AssertInvariant(self.get_all_server_metadata) as metadata: |
|
796 |
for vm in VirtualMachine.objects.all(): |
|
797 |
response_metadata = self.list_server_metadata(vm.id) |
|
798 |
self.assertEqual(response_metadata, metadata[vm.id]) |
|
799 |
|
|
800 |
def test_invalid_server(self): |
|
801 |
with AssertInvariant(self.get_all_server_metadata): |
|
802 |
response = self.client.get('/api/v1.1/servers/0/meta') |
|
803 |
self.assertItemNotFound(response) |
|
804 |
|
|
805 |
|
|
806 |
class UpdateServerMetadata(BaseTestCase): |
|
807 |
SERVER_METADATA = 10 |
|
808 |
|
|
809 |
def test_update_metadata(self): |
|
810 |
metadata = self.get_all_server_metadata() |
|
811 |
server_id = choice(metadata.keys()) |
|
812 |
new_metadata = {} |
|
813 |
for key in sample(metadata[server_id].keys(), 3): |
|
814 |
new_metadata[key] = 'New %s value' % key |
|
815 |
response_metadata = self.update_server_metadata(server_id, |
|
816 |
new_metadata) |
|
817 |
metadata[server_id].update(new_metadata) |
|
818 |
self.assertEqual(response_metadata, metadata[server_id]) |
|
819 |
self.assertEqual(metadata, self.get_all_server_metadata()) |
|
820 |
|
|
821 |
def test_invalid_data(self): |
|
822 |
with AssertInvariant(self.get_all_server_metadata) as metadata: |
|
823 |
server_id = choice(metadata.keys()) |
|
824 |
path = '/api/v1.1/servers/%d/meta' % server_id |
|
825 |
response = self.client.post(path, 'metadata', content_type='application/json') |
|
826 |
self.assertBadRequest(response) |
|
827 |
|
|
828 |
def test_invalid_server(self): |
|
829 |
with AssertInvariant(self.get_all_server_metadata): |
|
830 |
path = '/api/v1.1/servers/0/meta' |
|
831 |
data = json.dumps({'metadata': {'Key1': 'A Value'}}) |
|
832 |
response = self.client.post(path, data, content_type='application/json') |
|
833 |
self.assertItemNotFound(response) |
|
834 |
|
|
835 |
|
|
836 |
class GetServerMetadataItem(BaseTestCase): |
|
837 |
SERVERS = 5 |
|
838 |
SERVER_METADATA = 100 |
|
839 |
|
|
840 |
def test_get_metadata_item(self): |
|
841 |
with AssertInvariant(self.get_all_server_metadata) as metadata: |
|
842 |
server_id = choice(metadata.keys()) |
|
843 |
key = choice(metadata[server_id].keys()) |
|
844 |
path = '/api/v1.1/servers/%d/meta/%s' % (server_id, key) |
|
845 |
response = self.client.get(path) |
|
846 |
self.assertTrue(response.status_code in (200, 203)) |
|
847 |
reply = json.loads(response.content) |
|
848 |
self.assertEqual(reply['meta'], {key: metadata[server_id][key]}) |
|
849 |
|
|
850 |
def test_invalid_key(self): |
|
851 |
with AssertInvariant(self.get_all_server_metadata) as metadata: |
|
852 |
server_id = choice(metadata.keys()) |
|
853 |
response = self.client.get('/api/v1.1/servers/%d/meta/foo' % server_id) |
|
854 |
self.assertItemNotFound(response) |
|
855 |
|
|
856 |
def test_invalid_server(self): |
|
857 |
with AssertInvariant(self.get_all_server_metadata): |
|
858 |
response = self.client.get('/api/v1.1/servers/0/meta/foo') |
|
859 |
self.assertItemNotFound(response) |
|
860 |
|
|
861 |
|
|
862 |
class CreateServerMetadataItem(BaseTestCase): |
|
863 |
SERVER_METADATA = 10 |
|
864 |
|
|
865 |
def test_create_metadata(self): |
|
866 |
metadata = self.get_all_server_metadata() |
|
867 |
server_id = choice(metadata.keys()) |
|
868 |
meta = {'Foo': 'Bar'} |
|
869 |
self.create_server_meta(server_id, meta) |
|
870 |
metadata[server_id].update(meta) |
|
871 |
self.assertEqual(metadata, self.get_all_server_metadata()) |
|
872 |
|
|
873 |
def test_update_metadata(self): |
|
874 |
metadata = self.get_all_server_metadata() |
|
875 |
server_id = choice(metadata.keys()) |
|
876 |
key = choice(metadata[server_id].keys()) |
|
877 |
meta = {key: 'New Value'} |
|
878 |
self.create_server_meta(server_id, meta) |
|
879 |
metadata[server_id].update(meta) |
|
880 |
self.assertEqual(metadata, self.get_all_server_metadata()) |
|
881 |
|
|
882 |
def test_invalid_server(self): |
|
883 |
with AssertInvariant(self.get_all_server_metadata): |
|
884 |
path = '/api/v1.1/servers/0/meta/foo' |
|
885 |
data = json.dumps({'meta': {'foo': 'bar'}}) |
|
886 |
response = self.client.put(path, data, content_type='application/json') |
|
887 |
self.assertItemNotFound(response) |
|
888 |
|
|
889 |
def test_invalid_key(self): |
|
890 |
with AssertInvariant(self.get_all_server_metadata) as metadata: |
|
891 |
server_id = choice(metadata.keys()) |
|
892 |
path = '/api/v1.1/servers/%d/meta/baz' % server_id |
|
893 |
data = json.dumps({'meta': {'foo': 'bar'}}) |
|
894 |
response = self.client.put(path, data, content_type='application/json') |
|
895 |
self.assertBadRequest(response) |
|
896 |
|
|
897 |
def test_invalid_data(self): |
|
898 |
with AssertInvariant(self.get_all_server_metadata) as metadata: |
|
899 |
server_id = choice(metadata.keys()) |
|
900 |
path = '/api/v1.1/servers/%d/meta/foo' % server_id |
|
901 |
response = self.client.put(path, 'meta', content_type='application/json') |
|
902 |
self.assertBadRequest(response) |
|
903 |
|
|
904 |
|
|
905 |
class DeleteServerMetadataItem(BaseTestCase): |
|
906 |
SERVER_METADATA = 10 |
|
907 |
|
|
908 |
def test_delete_metadata(self): |
|
909 |
metadata = self.get_all_server_metadata() |
|
910 |
server_id = choice(metadata.keys()) |
|
911 |
key = choice(metadata[server_id].keys()) |
|
912 |
path = '/api/v1.1/servers/%d/meta/%s' % (server_id, key) |
|
913 |
response = self.client.delete(path) |
|
914 |
self.assertEqual(response.status_code, 204) |
|
915 |
metadata[server_id].pop(key) |
|
916 |
self.assertEqual(metadata, self.get_all_server_metadata()) |
|
917 |
|
|
918 |
def test_invalid_server(self): |
|
919 |
with AssertInvariant(self.get_all_server_metadata): |
|
920 |
response = self.client.delete('/api/v1.1/servers/9/meta/Key1') |
|
921 |
self.assertItemNotFound(response) |
|
922 |
|
|
923 |
def test_invalid_key(self): |
|
924 |
with AssertInvariant(self.get_all_server_metadata) as metadata: |
|
925 |
server_id = choice(metadata.keys()) |
|
926 |
path = '/api/v1.1/servers/%d/meta/foo' % server_id |
|
927 |
response = self.client.delete(path) |
|
928 |
self.assertItemNotFound(response) |
|
929 |
|
|
930 |
|
|
931 |
class ListImageMetadata(BaseTestCase): |
|
932 |
IMAGES = 5 |
|
933 |
IMAGE_METADATA = 100 |
|
640 |
def test_add_nic_malformed(self, mrapi): |
|
641 |
user = 'userr' |
|
642 |
vm = mfactory.VirtualMachineFactory(name='yo', userid=user) |
|
643 |
net = mfactory.NetworkFactory(state='ACTIVE', userid=user) |
|
644 |
request = {'add': {'serveRef': vm.id}} |
|
645 |
response = self.post('/api/v1.1/networks/%d/action' % net.id, |
|
646 |
net.userid, json.dumps(request), 'json') |
|
647 |
self.assertBadRequest(response) |
|
934 | 648 |
|
935 |
def test_list_metadata(self): |
|
936 |
with AssertInvariant(self.get_all_image_metadata) as metadata: |
|
937 |
for image in Image.objects.all(): |
|
938 |
response_metadata = self.list_image_metadata(image.id) |
|
939 |
self.assertEqual(response_metadata, metadata[image.id]) |
|
940 |
|
|
941 |
def test_invalid_image(self): |
|
942 |
with AssertInvariant(self.get_all_image_metadata): |
|
943 |
response = self.client.get('/api/v1.1/images/0/meta') |
|
944 |
self.assertItemNotFound(response) |
|
945 |
|
|
946 |
|
|
947 |
class UpdateImageMetadata(BaseTestCase): |
|
948 |
IMAGE_METADATA = 10 |
|
949 |
|
|
950 |
def test_update_metadata(self): |
|
951 |
metadata = self.get_all_image_metadata() |
|
952 |
image_id = choice(metadata.keys()) |
|
953 |
new_metadata = {} |
|
954 |
for key in sample(metadata[image_id].keys(), 3): |
|
955 |
new_metadata[key] = 'New %s value' % key |
|
956 |
response_metadata = self.update_image_metadata(image_id, new_metadata) |
|
957 |
metadata[image_id].update(new_metadata) |
|
958 |
self.assertEqual(response_metadata, metadata[image_id]) |
|
959 |
self.assertEqual(metadata, self.get_all_image_metadata()) |
|
960 |
|
|
961 |
def test_invalid_data(self): |
|
962 |
with AssertInvariant(self.get_all_image_metadata) as metadata: |
|
963 |
image_id = choice(metadata.keys()) |
|
964 |
path = '/api/v1.1/images/%d/meta' % image_id |
|
965 |
response = self.client.post(path, 'metadata', content_type='application/json') |
|
966 |
self.assertBadRequest(response) |
|
967 |
|
|
968 |
def test_invalid_server(self): |
|
969 |
with AssertInvariant(self.get_all_image_metadata): |
|
970 |
path = '/api/v1.1/images/0/meta' |
|
971 |
data = json.dumps({'metadata': {'Key1': 'A Value'}}) |
|
972 |
response = self.client.post(path, data, content_type='application/json') |
|
973 |
self.assertItemNotFound(response) |
|
649 |
def test_remove_nic(self, mrapi): |
|
650 |
user = 'userr' |
|
651 |
vm = mfactory.VirtualMachineFactory(name='yo', userid=user) |
|
652 |
net = mfactory.NetworkFactory(state='ACTIVE', userid=user) |
|
653 |
nic = mfactory.NetworkInterfaceFactory(machine=vm, network=net) |
|
654 |
request = {'remove': {'attachment': 'nic-%s-%s' % (vm.id, nic.index)}} |
|
655 |
response = self.post('/api/v1.1/networks/%d/action' % net.id, |
|
656 |
net.userid, json.dumps(request), 'json') |
|
657 |
self.assertEqual(response.status_code, 202) |
|
658 |
self.assertTrue(NetworkInterface.objects.get(id=nic.id).dirty) |
|
659 |
# Remove dirty nic |
|
660 |
response = self.post('/api/v1.1/networks/%d/action' % net.id, |
|
661 |
net.userid, json.dumps(request), 'json') |
|
662 |
self.assertFault(response, 409, 'buildInProgress') |
|
663 |
|
|
664 |
def test_remove_nic_malformed(self, mrapi): |
|
665 |
user = 'userr' |
|
666 |
vm = mfactory.VirtualMachineFactory(name='yo', userid=user) |
|
667 |
net = mfactory.NetworkFactory(state='ACTIVE', userid=user) |
|
668 |
nic = mfactory.NetworkInterfaceFactory(machine=vm, network=net) |
|
669 |
request = {'remove': |
|
670 |
{'att234achment': 'nic-%s-%s' % (vm.id, nic.index)} |
|
671 |
} |
|
672 |
response = self.post('/api/v1.1/networks/%d/action' % net.id, |
|
673 |
net.userid, json.dumps(request), 'json') |
|
674 |
self.assertBadRequest(response) |
|
974 | 675 |
|
975 | 676 |
|
976 | 677 |
class ServerVNCConsole(BaseTestCase): |
977 |
SERVERS = 1 |
|
978 | 678 |
|
979 | 679 |
def test_not_active_server(self): |
980 |
"""Test console req for server not in ACTIVE state returns badRequest""" |
|
981 |
server_id = choice(VirtualMachine.objects.all()).id |
|
982 |
path = '/api/v1.1/servers/%d/action' % server_id |
|
680 |
"""Test console req for not ACTIVE server returns badRequest""" |
|
681 |
vm = mfactory.VirtualMachineFactory() |
|
983 | 682 |
data = json.dumps({'console': {'type': 'vnc'}}) |
984 |
response = self.client.post(path, data, content_type='application/json') |
|
683 |
response = self.post('/api/v1.1/servers/%d/action' % vm.id, |
|
684 |
vm.userid, data, 'json') |
|
985 | 685 |
self.assertBadRequest(response) |
986 | 686 |
|
987 | 687 |
def test_active_server(self): |
988 | 688 |
"""Test console req for ACTIVE server""" |
989 |
server_id = choice(VirtualMachine.objects.all()).id |
|
990 |
# FIXME: Start the server properly, instead of tampering with the DB |
|
991 |
vm = choice(VirtualMachine.objects.all()) |
|
689 |
vm = mfactory.VirtualMachineFactory() |
|
992 | 690 |
vm.operstate = 'STARTED' |
993 | 691 |
vm.save() |
994 |
server_id = vm.id |
|
995 | 692 |
|
996 |
path = '/api/v1.1/servers/%d/action' % server_id |
|
997 | 693 |
data = json.dumps({'console': {'type': 'vnc'}}) |
998 |
response = self.client.post(path, data, content_type='application/json') |
|
694 |
response = self.post('/api/v1.1/servers/%d/action' % vm.id, |
|
695 |
vm.userid, data, 'json') |
|
999 | 696 |
self.assertEqual(response.status_code, 200) |
1000 | 697 |
reply = json.loads(response.content) |
1001 | 698 |
self.assertEqual(reply.keys(), ['console']) |
1002 | 699 |
console = reply['console'] |
1003 | 700 |
self.assertEqual(console['type'], 'vnc') |
1004 |
self.assertEqual(set(console.keys()), set(['type', 'host', 'port', 'password'])) |
|
1005 |
|
|
1006 |
|
|
1007 |
class AaiTestCase(TestCase): |
|
1008 |
fixtures = ['users', 'api_test_data', 'auth_test_data'] |
|
1009 |
apibase = '/api/v1.1' |
|
1010 |
|
|
701 |
self.assertEqual(set(console.keys()), |
|
702 |
set(['type', 'host', 'port', 'password'])) |
|
703 |
|
|
704 |
|
|
705 |
@patch('synnefo.api.images.ImageBackend') |
|
706 |
class ImageAPITest(BaseTestCase): |
|
707 |
def test_create_image(self, mimage): |
|
708 |
"""Test that create image is not implemented""" |
|
709 |
response = self.post('/api/v1.1/images/', 'user', json.dumps(''), |
|
710 |
'json') |
|
711 |
self.assertEqual(response.status_code, 503) |
|
712 |
|
|
713 |
def test_list_images(self, mimage): |
|
714 |
"""Test that expected list of images is returned""" |
|
715 |
images = [{'id': 1, 'name': 'image-1'}, |
|
716 |
{'id': 2, 'name': 'image-2'}, |
|
717 |
{'id': 3, 'name': 'image-3'}] |
|
718 |
mimage().list.return_value = images |
|
719 |
response = self.get('/api/v1.1/images/', 'user') |
Also available in: Unified diff