Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / compute / test.py @ 99e4d887

History | View | Annotate | Download (27 kB)

1
# Copyright 2013 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
from mock import patch, call
35
from unittest import TestCase
36
from itertools import product
37
from json import dumps
38
from sys import stdout
39

    
40
from kamaki.clients import ClientError, compute
41

    
42

    
43
rest_pkg = 'kamaki.clients.compute.rest_api.ComputeRestClient'
44
compute_pkg = 'kamaki.clients.compute.ComputeClient'
45

    
46
img_ref = "1m4g3-r3f3r3nc3"
47
vm_name = "my new VM"
48
fid = 42
49
vm_send = dict(server=dict(
50
    flavorRef=fid,
51
    name=vm_name,
52
    imageRef=img_ref,
53
    metadata=dict(os="debian", users="root")))
54
vm_recv = dict(server=dict(
55
    status="BUILD",
56
    updated="2013-03-01T10:04:00.637152+00:00",
57
    hostId="",
58
    name=vm_name,
59
    imageRef=img_ref,
60
    created="2013-03-01T10:04:00.087324+00:00",
61
    flavorRef=fid,
62
    adminPass="n0n3sh@11p@55",
63
    suspended=False,
64
    progress=0,
65
    id=31173,
66
    metadata=dict(os="debian", users="root")))
67
img_recv = dict(image=dict(
68
    status="ACTIVE",
69
    updated="2013-02-26T11:10:14+00:00",
70
    name="Debian Base",
71
    created="2013-02-26T11:03:29+00:00",
72
    progress=100,
73
    id=img_ref,
74
    metadata=dict(
75
        partition_table="msdos",
76
        kernel="2.6.32",
77
        osfamily="linux",
78
        users="root",
79
        gui="No GUI",
80
        sortorder="1",
81
        os="debian",
82
        root_partition="1",
83
        description="Debian 6.0.7 (Squeeze) Base System")))
84
vm_list = dict(servers=[
85
    dict(name='n1', id=1),
86
    dict(name='n2', id=2)])
87
flavor_list = dict(flavors=[
88
    dict(id=41, name="C1R1024D20"),
89
    dict(id=42, name="C1R1024D40"),
90
    dict(id=43, name="C1R1028D20")])
91
img_list = dict(images=[
92
    dict(name="maelstrom", id="0fb03e45-7d5a-4515-bd4e-e6bbf6457f06"),
93
    dict(name="edx_saas", id="1357163d-5fd8-488e-a117-48734c526206"),
94
    dict(name="Debian_Wheezy_Base", id="1f8454f0-8e3e-4b6c-ab8e-5236b728dffe"),
95
    dict(name="CentOS", id="21894b48-c805-4568-ac8b-7d4bb8eb533d"),
96
    dict(name="Ubuntu Desktop", id="37bc522c-c479-4085-bfb9-464f9b9e2e31"),
97
    dict(name="Ubuntu 12.10", id="3a24fef9-1a8c-47d1-8f11-e07bd5e544fd"),
98
    dict(name="Debian Base", id="40ace203-6254-4e17-a5cb-518d55418a7d"),
99
    dict(name="ubuntu_bundled", id="5336e265-5c7c-4127-95cb-2bf832a79903")])
100

    
101

    
102
class FR(object):
103
    """FR stands for Fake Response"""
104
    json = vm_recv
105
    headers = {}
106
    content = json
107
    status = None
108
    status_code = 200
109

    
110

    
111
def print_iterations(old, new):
112
    if new:
113
        if new % 1000:
114
            return old
115
        stdout.write('\b' * len('%s' % old))
116
        stdout.write('%s' % new)
117
    else:
118
        stdout.write('# of loops:  ')
119
    stdout.flush()
120
    return new
121

    
122

    
123
class ComputeRestClient(TestCase):
124

    
125
    """Set up a ComputesRest thorough test"""
126
    def setUp(self):
127
        self.url = 'http://cyclades.example.com'
128
        self.token = 'cyc14d3s70k3n'
129
        self.client = compute.ComputeRestClient(self.url, self.token)
130

    
131
    def tearDown(self):
132
        FR.json = vm_recv
133

    
134
    @patch('%s.get' % rest_pkg, return_value=FR())
135
    def test_limits_get(self, get):
136
        self.client.limits_get(success='some_val')
137
        get.assert_called_once_with('/limits', success='some_val')
138

    
139
    @patch('%s.set_param' % rest_pkg)
140
    @patch('%s.get' % rest_pkg, return_value=FR())
141
    def _test_get(self, service, params, get, set_param):
142
        method = getattr(self.client, '%s_get' % service)
143
        param_args = [({}, {k: k}, {k: v[1]}) for k, v in params.items()]
144
        num_of_its = 0
145
        for i, args in enumerate(product(
146
                ('', '%s_id' % service),
147
                (None, False, True),
148
                (200, 204),
149
                ({}, {'k': 'v'}),
150
                *param_args)):
151
            (srv_id, detail, success, kwargs) = args[:4]
152
            kwargs['success'] = success
153
            srv_kwargs = dict()
154
            for param in args[4:]:
155
                srv_kwargs.update(param)
156
            srv_kwargs.update(kwargs)
157
            method(*args[:2], **srv_kwargs)
158
            srv_str = '/detail' if detail else (
159
                '/%s' % srv_id) if srv_id else ''
160
            self.assertEqual(
161
                get.mock_calls[-1],
162
                call('/%s%s' % (service, srv_str), **kwargs))
163
            param_calls = []
164
            for k, v in params.items():
165
                real_v = srv_kwargs.get(k, v[1]) if not srv_id else v[1]
166
                param_calls.append(call(v[0], real_v, iff=real_v))
167
            actual = set_param.mock_calls[- len(param_calls):]
168
            self.assertEqual(sorted(actual), sorted(param_calls))
169

    
170
            num_of_its = print_iterations(num_of_its, i)
171
        print ('\b' * len('%s' % num_of_its)) + ('%s' % i)
172

    
173
    @patch('%s.set_param' % rest_pkg)
174
    @patch('%s.get' % rest_pkg, return_value=FR())
175
    def _test_srv_cmd_get(self, srv, cmd, params, get, set_param):
176
        method = getattr(self.client, '%s_%s_get' % (srv, cmd))
177
        param_args = [({}, {k: k}, {k: v[1]}) for k, v in params.items()]
178
        num_of_its = 0
179
        for i, args in enumerate(product(
180
                ('some_server_id', 'other_server_id'),
181
                (None, 'xtra_id'),
182
                ((304, 200), (1000)),
183
                ({}, {'k': 'v'}),
184
                *param_args)):
185
            srv_id, xtra_id, success, kwargs = args[:4]
186
            kwargs['success'] = success
187
            srv_kwargs = dict()
188
            for param in args[4:]:
189
                srv_kwargs.update(param)
190
            srv_kwargs.update(kwargs)
191
            method(*args[:2], **srv_kwargs)
192
            srv_str = '/%s/%s/%s' % (srv, srv_id, cmd)
193
            srv_str += ('/%s' % xtra_id) if xtra_id else ''
194
            self.assertEqual(get.mock_calls[-1], call(srv_str, **kwargs))
195
            param_calls = []
196
            for k, v in params.items():
197
                real_v = srv_kwargs.get(k, v[1])
198
                param_calls.append(call(v[0], real_v, iff=real_v))
199
            actual = set_param.mock_calls[- len(param_calls):]
200
            self.assertEqual(sorted(actual), sorted(param_calls))
201

    
202
            num_of_its = print_iterations(num_of_its, i)
203
        print ('\b' * len('%s' % num_of_its)) + ('%s' % i)
204

    
205
    @patch('%s.delete' % rest_pkg, return_value=FR())
206
    def _test_delete(self, srv, cmd, delete):
207
        method = getattr(
208
            self.client, '%s_%sdelete' % (srv, ('%s_' % cmd) if cmd else ''))
209
        cmd_params = ('some_cmd_value', 'some_other_value') if cmd else ()
210
        num_of_its = 0
211
        for i, args in enumerate(product(
212
                ('%s_id' % srv, 'some_value'),
213
                (204, 208),
214
                ({}, {'k': 'v'}),
215
                *cmd_params)):
216
            (srv_id, success, kwargs) = args[:3]
217
            kwargs['success'] = success
218
            cmd_value = args[-1] if cmd else ''
219
            method_args = (srv_id, cmd_value) if cmd else (srv_id, )
220
            method(*method_args, **kwargs)
221
            srv_str = '/%s/%s' % (srv, srv_id)
222
            cmd_str = ('/%s/%s' % (cmd, cmd_value)) if cmd else ''
223
            self.assertEqual(
224
                delete.mock_calls[-1],
225
                call('%s%s' % (srv_str, cmd_str), **kwargs))
226
            num_of_its = print_iterations(num_of_its, i)
227
        print ('\b' * len('%s' % num_of_its)) + ('%s' % i)
228

    
229
    def test_servers_get(self):
230
        params = dict(
231
            changes_since=('changes-since', None),
232
            image=('image', None),
233
            flavor=('flavor', None),
234
            name=('name', None),
235
            marker=('marker', None),
236
            limit=('limit', None),
237
            status=('status', None),
238
            host=('host', None))
239
        self._test_get('servers', params)
240

    
241
    def test_servers_metadata_get(self):
242
        self._test_srv_cmd_get('servers', 'metadata', {})
243

    
244
    def test_servers_ips_get(self):
245
        params = dict(changes_since=('changes-since', None))
246
        self._test_srv_cmd_get('servers', 'ips', params)
247

    
248
    def test_flavors_get(self):
249
        params = dict(
250
            changes_since=('changes-since', None),
251
            minDisk=('minDisk', None),
252
            minRam=('minRam', None),
253
            marker=('marker', None),
254
            limit=('limit', None))
255
        self._test_get('flavors', params)
256

    
257
    def test_images_get(self):
258
        param = dict(
259
            changes_since=('changes-since', None),
260
            server_name=('server', None),
261
            name=('name', None),
262
            status=('status', None),
263
            marker=('marker', None),
264
            limit=('limit', None),
265
            type=('type', None))
266
        self._test_get('images', param)
267

    
268
    def test_images_metadata_get(self):
269
        self._test_srv_cmd_get('images', 'metadata', {})
270

    
271
    def test_servers_delete(self):
272
        self._test_delete('servers', None)
273

    
274
    def test_servers_metadata_delete(self):
275
        self._test_delete('servers', 'metadata')
276

    
277
    def test_images_delete(self):
278
        self._test_delete('images', None)
279

    
280
    def test_images_metadata_delete(self):
281
        self._test_delete('images', 'metadata')
282

    
283
    @patch('%s.set_header' % rest_pkg)
284
    @patch('%s.post' % rest_pkg, return_value=FR())
285
    def _test_post(self, service, post, SH):
286
        for args in product(
287
                ('', '%s_id' % service),
288
                ('', 'cmd'),
289
                (None, [dict(json="data"), dict(data="json")]),
290
                (202, 204),
291
                ({}, {'k': 'v'})):
292
            (srv_id, command, json_data, success, kwargs) = args
293
            method = getattr(self.client, '%s_post' % service)
294
            method(*args[:4], **kwargs)
295
            vm_str = '/%s' % srv_id if srv_id else ''
296
            cmd_str = '/%s' % command if command else ''
297
            if json_data:
298
                json_data = dumps(json_data)
299
                self.assertEqual(SH.mock_calls[-2:], [
300
                    call('Content-Type', 'application/json'),
301
                    call('Content-Length', len(json_data))])
302
            self.assertEqual(post.mock_calls[-1], call(
303
                '/%s%s%s' % (service, vm_str, cmd_str),
304
                data=json_data, success=success,
305
                **kwargs))
306

    
307
    def test_servers_post(self):
308
        self._test_post('servers')
309

    
310
    def test_images_post(self):
311
        self._test_post('images')
312

    
313
    @patch('%s.set_header' % rest_pkg)
314
    @patch('%s.put' % rest_pkg, return_value=FR())
315
    def _test_put(self, service, put, SH):
316
        for args in product(
317
                ('', '%s_id' % service),
318
                ('', 'cmd'),
319
                (None, [dict(json="data"), dict(data="json")]),
320
                (204, 504),
321
                ({}, {'k': 'v'})):
322
            (server_id, command, json_data, success, kwargs) = args
323
            method = getattr(self.client, '%s_put' % service)
324
            method(*args[:4], **kwargs)
325
            vm_str = '/%s' % server_id if server_id else ''
326
            cmd_str = '/%s' % command if command else ''
327
            if json_data:
328
                json_data = dumps(json_data)
329
                self.assertEqual(SH.mock_calls[-2:], [
330
                    call('Content-Type', 'application/json'),
331
                    call('Content-Length', len(json_data))])
332
            self.assertEqual(put.mock_calls[-1], call(
333
                '/%s%s%s' % (service, vm_str, cmd_str),
334
                data=json_data, success=success,
335
                **kwargs))
336

    
337
    def test_servers_put(self):
338
        self._test_put('servers')
339

    
340
    def test_images_put(self):
341
        self._test_put('images')
342

    
343
    @patch('%s.get' % rest_pkg, return_value=FR())
344
    def test_floating_ip_pools_get(self, get):
345
        for args in product(
346
                ('tenant1', 'tenant2'),
347
                (200, 204),
348
                ({}, {'k': 'v'})):
349
            tenant_id, success, kwargs = args
350
            r = self.client.floating_ip_pools_get(tenant_id, success, **kwargs)
351
            self.assertTrue(isinstance(r, FR))
352
            self.assertEqual(get.mock_calls[-1], call(
353
                '/%s/os-floating-ip-pools' % tenant_id,
354
                success=success, **kwargs))
355

    
356
    @patch('%s.get' % rest_pkg, return_value=FR())
357
    def test_floating_ips_get(self, get):
358
        for args in product(
359
                ('tenant1', 'tenant2'),
360
                ('', '192.193.194.195'),
361
                (200, 204),
362
                ({}, {'k': 'v'})):
363
            tenant_id, ip, success, kwargs = args
364
            r = self.client.floating_ips_get(*args[:3], **kwargs)
365
            self.assertTrue(isinstance(r, FR))
366
            expected = '' if not ip else '/%s' % ip
367
            self.assertEqual(get.mock_calls[-1], call(
368
                '/%s/os-floating-ips%s' % (tenant_id, expected),
369
                success=success, **kwargs))
370

    
371
    @patch('%s.set_header' % rest_pkg)
372
    @patch('%s.post' % rest_pkg, return_value=FR())
373
    def test_floating_ips_post(self, post, SH):
374
        for args in product(
375
                ('tenant1', 'tenant2'),
376
                (None, [dict(json="data"), dict(data="json")]),
377
                ('', '192.193.194.195'),
378
                (202, 204),
379
                ({}, {'k': 'v'})):
380
            (tenant_id, json_data, ip, success, kwargs) = args
381
            self.client.floating_ips_post(*args[:4], **kwargs)
382
            if json_data:
383
                json_data = dumps(json_data)
384
                self.assertEqual(SH.mock_calls[-2:], [
385
                    call('Content-Type', 'application/json'),
386
                    call('Content-Length', len(json_data))])
387
            expected = '' if not ip else '/%s' % ip
388
            self.assertEqual(post.mock_calls[-1], call(
389
                '/%s/os-floating-ips%s' % (tenant_id, expected),
390
                data=json_data, success=success,
391
                **kwargs))
392

    
393
    @patch('%s.delete' % rest_pkg, return_value=FR())
394
    def test_floating_ips_delete(self, delete):
395
        for args in product(
396
                ('tenant1', 'tenant2'),
397
                ('', '192.193.194.195'),
398
                (204,),
399
                ({}, {'k': 'v'})):
400
            tenant_id, ip, success, kwargs = args
401
            r = self.client.floating_ips_delete(*args[:3], **kwargs)
402
            self.assertTrue(isinstance(r, FR))
403
            expected = '' if not ip else '/%s' % ip
404
            self.assertEqual(delete.mock_calls[-1], call(
405
                '/%s/os-floating-ips%s' % (tenant_id, expected),
406
                success=success, **kwargs))
407

    
408

    
409
class ComputeClient(TestCase):
410

    
411
    def assert_dicts_are_equal(self, d1, d2):
412
        for k, v in d1.items():
413
            self.assertTrue(k in d2)
414
            if isinstance(v, dict):
415
                self.assert_dicts_are_equal(v, d2[k])
416
            else:
417
                self.assertEqual(unicode(v), unicode(d2[k]))
418

    
419
    """Set up a Cyclades thorough test"""
420
    def setUp(self):
421
        self.url = 'http://cyclades.example.com'
422
        self.token = 'cyc14d3s70k3n'
423
        self.client = compute.ComputeClient(self.url, self.token)
424

    
425
    def tearDown(self):
426
        FR.status_code = 200
427
        FR.json = vm_recv
428

    
429
    @patch(
430
        '%s.get_image_details' % compute_pkg,
431
        return_value=img_recv['image'])
432
    def test_create_server(self, GID):
433
        with patch.object(
434
                compute.ComputeClient, 'servers_post',
435
                side_effect=ClientError(
436
                    'REQUEST ENTITY TOO LARGE',
437
                    status=403)):
438
            self.assertRaises(
439
                ClientError,
440
                self.client.create_server,
441
                vm_name, fid, img_ref)
442

    
443
        with patch.object(
444
                compute.ComputeClient, 'servers_post',
445
                return_value=FR()) as post:
446
            r = self.client.create_server(vm_name, fid, img_ref)
447
            self.assertEqual(r, FR.json['server'])
448
            self.assertEqual(GID.mock_calls[-1], call(img_ref))
449
            self.assertEqual(post.mock_calls[-1], call(json_data=vm_send))
450
            prsn = 'Personality string (does not work with real servers)'
451
            self.client.create_server(vm_name, fid, img_ref, prsn)
452
            expected = dict(server=dict(vm_send['server']))
453
            expected['server']['personality'] = prsn
454
            self.assertEqual(post.mock_calls[-1], call(json_data=expected))
455

    
456
    @patch('%s.servers_get' % compute_pkg, return_value=FR())
457
    def test_list_servers(self, SG):
458
        FR.json = vm_list
459
        for detail in (False, True):
460
            r = self.client.list_servers(detail)
461
            self.assertEqual(SG.mock_calls[-1], call(
462
                command='detail' if detail else ''))
463
            for i, vm in enumerate(vm_list['servers']):
464
                self.assert_dicts_are_equal(r[i], vm)
465
            self.assertEqual(i + 1, len(r))
466

    
467
    @patch('%s.servers_get' % compute_pkg, return_value=FR())
468
    def test_get_server_details(self, SG):
469
        vm_id = vm_recv['server']['id']
470
        r = self.client.get_server_details(vm_id)
471
        SG.assert_called_once_with(vm_id)
472
        self.assert_dicts_are_equal(r, vm_recv['server'])
473

    
474
    @patch('%s.servers_put' % compute_pkg, return_value=FR())
475
    def test_update_server_name(self, SP):
476
        vm_id = vm_recv['server']['id']
477
        new_name = vm_name + '_new'
478
        self.client.update_server_name(vm_id, new_name)
479
        SP.assert_called_once_with(vm_id, json_data=dict(
480
            server=dict(name=new_name)))
481

    
482
    @patch('%s.servers_post' % compute_pkg, return_value=FR())
483
    def test_reboot_server(self, SP):
484
        vm_id = vm_recv['server']['id']
485
        for hard in (None, True):
486
            self.client.reboot_server(vm_id, hard=hard)
487
            self.assertEqual(SP.mock_calls[-1], call(
488
                vm_id, 'action',
489
                json_data=dict(reboot=dict(type='HARD' if hard else 'SOFT'))))
490

    
491
    @patch('%s.servers_post' % compute_pkg, return_value=FR())
492
    def test_resize_server(self, SP):
493
        vm_id, flavor = vm_recv['server']['id'], flavor_list['flavors'][1]
494
        self.client.resize_server(vm_id, flavor['id'])
495
        exp = dict(resize=dict(flavorRef=flavor['id']))
496
        SP.assert_called_once_with(vm_id, 'action', json_data=exp)
497

    
498
    @patch('%s.servers_put' % compute_pkg, return_value=FR())
499
    def test_create_server_metadata(self, SP):
500
        vm_id = vm_recv['server']['id']
501
        metadata = dict(m1='v1', m2='v2', m3='v3')
502
        FR.json = dict(meta=vm_recv['server'])
503
        for k, v in metadata.items():
504
            r = self.client.create_server_metadata(vm_id, k, v)
505
            self.assert_dicts_are_equal(r, vm_recv['server'])
506
            self.assertEqual(SP.mock_calls[-1], call(
507
                vm_id, 'metadata/%s' % k,
508
                json_data=dict(meta={k: v}), success=201))
509

    
510
    @patch('%s.servers_get' % compute_pkg, return_value=FR())
511
    def test_get_server_metadata(self, SG):
512
        vm_id = vm_recv['server']['id']
513
        metadata = dict(m1='v1', m2='v2', m3='v3')
514
        FR.json = dict(metadata=metadata)
515
        r = self.client.get_server_metadata(vm_id)
516
        FR.json = dict(meta=metadata)
517
        SG.assert_called_once_with(vm_id, '/metadata')
518
        self.assert_dicts_are_equal(r, metadata)
519

    
520
        for k, v in metadata.items():
521
            FR.json = dict(meta={k: v})
522
            r = self.client.get_server_metadata(vm_id, k)
523
            self.assert_dicts_are_equal(r, {k: v})
524
            self.assertEqual(
525
                SG.mock_calls[-1], call(vm_id, '/metadata/%s' % k))
526

    
527
    @patch('%s.servers_post' % compute_pkg, return_value=FR())
528
    def test_update_server_metadata(self, SP):
529
        vm_id = vm_recv['server']['id']
530
        metadata = dict(m1='v1', m2='v2', m3='v3')
531
        FR.json = dict(metadata=metadata)
532
        r = self.client.update_server_metadata(vm_id, **metadata)
533
        self.assert_dicts_are_equal(r, metadata)
534
        SP.assert_called_once_with(
535
            vm_id, 'metadata',
536
            json_data=dict(metadata=metadata), success=201)
537

    
538
    @patch('%s.servers_delete' % compute_pkg, return_value=FR())
539
    def test_delete_server_metadata(self, SD):
540
        vm_id = vm_recv['server']['id']
541
        key = 'metakey'
542
        self.client.delete_server_metadata(vm_id, key)
543
        SD.assert_called_once_with(vm_id, 'metadata/' + key)
544

    
545
    @patch('%s.flavors_get' % compute_pkg, return_value=FR())
546
    def test_list_flavors(self, FG):
547
        FR.json = flavor_list
548
        for cmd in ('', 'detail'):
549
            r = self.client.list_flavors(detail=(cmd == 'detail'))
550
            self.assertEqual(FG.mock_calls[-1], call(command=cmd))
551
            self.assertEqual(r, flavor_list['flavors'])
552

    
553
    @patch('%s.flavors_get' % compute_pkg, return_value=FR())
554
    def test_get_flavor_details(self, FG):
555
        FR.json = dict(flavor=flavor_list['flavors'][0])
556
        r = self.client.get_flavor_details(fid)
557
        FG.assert_called_once_with(fid)
558
        self.assert_dicts_are_equal(r, flavor_list['flavors'][0])
559

    
560
    @patch('%s.images_get' % compute_pkg, return_value=FR())
561
    def test_list_images(self, IG):
562
        FR.json = img_list
563
        for cmd in ('', 'detail'):
564
            r = self.client.list_images(detail=(cmd == 'detail'))
565
            self.assertEqual(IG.mock_calls[-1], call(command=cmd))
566
            expected = img_list['images']
567
            for i in range(len(r)):
568
                self.assert_dicts_are_equal(expected[i], r[i])
569

    
570
    @patch('%s.images_get' % compute_pkg, return_value=FR())
571
    def test_get_image_details(self, IG):
572
        FR.json = img_recv
573
        r = self.client.get_image_details(img_ref)
574
        IG.assert_called_once_with(img_ref)
575
        self.assert_dicts_are_equal(r, img_recv['image'])
576

    
577
    @patch('%s.images_get' % compute_pkg, return_value=FR())
578
    def test_get_image_metadata(self, IG):
579
        for key in ('', '50m3k3y'):
580
            FR.json = dict(meta=img_recv['image']) if (
581
                key) else dict(metadata=img_recv['image'])
582
            r = self.client.get_image_metadata(img_ref, key)
583
            self.assertEqual(IG.mock_calls[-1], call(
584
                '%s' % img_ref,
585
                '/metadata%s' % (('/%s' % key) if key else '')))
586
            self.assert_dicts_are_equal(img_recv['image'], r)
587

    
588
    @patch('%s.servers_delete' % compute_pkg, return_value=FR())
589
    def test_delete_server(self, SD):
590
        vm_id = vm_recv['server']['id']
591
        self.client.delete_server(vm_id)
592
        SD.assert_called_once_with(vm_id)
593

    
594
    @patch('%s.images_delete' % compute_pkg, return_value=FR())
595
    def test_delete_image(self, ID):
596
        self.client.delete_image(img_ref)
597
        ID.assert_called_once_with(img_ref)
598

    
599
    @patch('%s.images_put' % compute_pkg, return_value=FR())
600
    def test_create_image_metadata(self, IP):
601
        (key, val) = ('k1', 'v1')
602
        FR.json = dict(meta=img_recv['image'])
603
        r = self.client.create_image_metadata(img_ref, key, val)
604
        IP.assert_called_once_with(
605
            img_ref, 'metadata/%s' % key,
606
            json_data=dict(meta={key: val}))
607
        self.assert_dicts_are_equal(r, img_recv['image'])
608

    
609
    @patch('%s.images_post' % compute_pkg, return_value=FR())
610
    def test_update_image_metadata(self, IP):
611
        metadata = dict(m1='v1', m2='v2', m3='v3')
612
        FR.json = dict(metadata=metadata)
613
        r = self.client.update_image_metadata(img_ref, **metadata)
614
        IP.assert_called_once_with(
615
            img_ref, 'metadata',
616
            json_data=dict(metadata=metadata))
617
        self.assert_dicts_are_equal(r, metadata)
618

    
619
    @patch('%s.images_delete' % compute_pkg, return_value=FR())
620
    def test_delete_image_metadata(self, ID):
621
        key = 'metakey'
622
        self.client.delete_image_metadata(img_ref, key)
623
        ID.assert_called_once_with(img_ref, '/metadata/%s' % key)
624

    
625
    @patch('%s.floating_ip_pools_get' % compute_pkg, return_value=FR())
626
    def test_get_floating_ip_pools(self, get):
627
        tid = 't3n@nt_1d'
628
        r = self.client.get_floating_ip_pools(tid)
629
        self.assert_dicts_are_equal(r, FR.json)
630
        self.assertEqual(get.mock_calls[-1], call(tid))
631

    
632
    @patch('%s.floating_ips_get' % compute_pkg, return_value=FR())
633
    def test_get_floating_ips(self, get):
634
        tid = 't3n@nt_1d'
635
        r = self.client.get_floating_ips(tid)
636
        self.assert_dicts_are_equal(r, FR.json)
637
        self.assertEqual(get.mock_calls[-1], call(tid))
638

    
639
    @patch('%s.floating_ips_post' % compute_pkg, return_value=FR())
640
    def test_alloc_floating_ip(self, post):
641
        FR.json = dict(floating_ip=dict(
642
            fixed_ip='fip',
643
            id=1,
644
            instance_id='lala',
645
            ip='102.0.0.1',
646
            pool='pisine'))
647
        for args in product(
648
                ('t1', 't2'),
649
                (None, 'pisine')):
650
            r = self.client.alloc_floating_ip(*args)
651
            tenant_id, pool = args
652
            self.assert_dicts_are_equal(r, FR.json['floating_ip'])
653
            expected = dict(pool=pool) if pool else dict()
654
            self.assertEqual(post.mock_calls[-1], call(tenant_id, expected))
655

    
656
    @patch('%s.floating_ips_get' % compute_pkg, return_value=FR())
657
    def test_get_floating_ip(self, get):
658
        FR.json = dict(floating_ips=[dict(
659
            fixed_ip='fip',
660
            id=1,
661
            instance_id='lala',
662
            ip='102.0.0.1',
663
            pool='pisine'), ])
664
        for args in product(
665
                ('t1', 't2'),
666
                (None, 'fip')):
667
            r = self.client.get_floating_ip(*args)
668
            tenant_id, fip = args
669
            self.assertEqual(r, FR.json['floating_ips'])
670
            self.assertEqual(get.mock_calls[-1], call(tenant_id, fip))
671

    
672
    @patch('%s.floating_ips_delete' % compute_pkg, return_value=FR())
673
    def test_delete_floating_ip(self, delete):
674
        for args in product(
675
                ('t1', 't2'),
676
                (None, 'fip')):
677
            r = self.client.delete_floating_ip(*args)
678
            tenant_id, fip = args
679
            self.assertEqual(r, FR.headers)
680
            self.assertEqual(delete.mock_calls[-1], call(tenant_id, fip))
681

    
682

    
683
if __name__ == '__main__':
684
    from sys import argv
685
    from kamaki.clients.test import runTestCase
686
    not_found = True
687
    if not argv[1:] or argv[1] == 'ComputeClient':
688
        not_found = False
689
        runTestCase(ComputeClient, 'Compute Client', argv[2:])
690
    if not argv[1:] or argv[1] == 'ComputeRest':
691
        not_found = False
692
        runTestCase(ComputeRestClient, 'ComputeRest Client', argv[2:])
693
    if not_found:
694
        print('TestCase %s not found' % argv[1])