Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / compute / test.py @ ca5528f1

History | View | Annotate | Download (31.5 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
import json
40

    
41
from kamaki.clients import ClientError, compute
42

    
43

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

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

    
102

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

    
111

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

    
123

    
124
class ComputeRestClient(TestCase):
125

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

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

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

    
166
            num_of_its = print_iterations(num_of_its, i)
167
        print ('\b' * len('%s' % num_of_its)) + ('%s' % i)
168

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

    
199
            num_of_its = print_iterations(num_of_its, i)
200
        print ('\b' * len('%s' % num_of_its)) + ('%s' % i)
201

    
202
    @patch('%s.set_header' % rest_pkg)
203
    @patch('%s.set_param' % rest_pkg)
204
    @patch('%s.post' % rest_pkg, return_value=FR())
205
    def _test_post(self, srv, cmd, params, post, set_param, set_header):
206
        method = getattr(
207
            self.client, '%s_%spost' % (srv, ('%s_' % cmd) if cmd else ''))
208
        param_args = [({}, {k: k}, {k: v[1]}) for k, v in params.items()]
209
        num_of_its = 0
210
        for i, args in enumerate(product(
211
                ('%s_id' % srv, 'some_value'),
212
                (
213
                    None,
214
                    {'some': {'data': 'in json'}},
215
                    ['k1', {'k2': 'v2', 'k3': 'v3'}, 'k4']),
216
                (202, 1453),
217
                ({}, {'k': 'v'}),
218
                *param_args)):
219
            srv_id, json_data, success, kwargs = args[:4]
220
            kwargs = dict(kwargs)
221
            cmd_args = (srv_id, ) if cmd else ()
222
            kwargs['success'] = success
223
            srv_kwargs = dict()
224
            for param in args[4:]:
225
                srv_kwargs.update(param)
226
            srv_kwargs.update(kwargs)
227
            srv_kwargs['json_data'] = json_data
228
            method(*cmd_args, **srv_kwargs)
229
            srv_str = '/%s%s' % (
230
                srv, (('/%s/%s' % (srv_id, cmd)) if cmd else ''))
231
            kwargs['data'] = json.dumps(json_data) if json_data else None
232
            self.assertEqual(post.mock_calls[-1], call(srv_str, **kwargs))
233

    
234
            param_calls = []
235
            for k, v in params.items():
236
                real_v = srv_kwargs.get(k, v[1])
237
                param_calls.append(call(v[0], real_v, iff=real_v))
238
            actual = set_param.mock_calls[- len(param_calls):]
239
            self.assertEqual(sorted(actual), sorted(param_calls))
240

    
241
            if json_data:
242
                self.assertEqual(set_header.mock_calls[-2:], [
243
                    call('Content-Type', 'application/json'),
244
                    call('Content-Length', len(kwargs['data']))])
245

    
246
            num_of_its = print_iterations(num_of_its, i)
247
        print ('\b' * len('%s' % num_of_its)) + ('%s' % i)
248

    
249
    @patch('%s.set_header' % rest_pkg)
250
    @patch('%s.set_param' % rest_pkg)
251
    @patch('%s.put' % rest_pkg, return_value=FR())
252
    def _test_put(self, srv, cmd, params, put, set_param, set_headers):
253
        method = getattr(self.client, '%s_%sput' % (
254
            srv, ('%s_' % cmd) if cmd else ''))
255
        param_args = [({}, {k: k}, {k: v[1]}) for k, v in params.items()]
256
        num_of_its = 0
257
        for i, args in enumerate(product(
258
                ('some_value', '%s_id' % srv),
259
                (None, [dict(json="data"), dict(data="json")]),
260
                (204, 504),
261
                ({}, {'k': 'v'}),
262
                *param_args)):
263
            srv_id, json_data, success, kwargs = args[:4]
264
            kwargs = dict(kwargs)
265
            kwargs['success'] = success
266
            srv_kwargs = dict()
267
            for param in args[4:]:
268
                srv_kwargs.update(param)
269
            srv_kwargs.update(kwargs)
270
            srv_kwargs['json_data'] = json_data
271
            method(srv_id, **srv_kwargs)
272
            srv_str = '/%s/%s%s' % (srv, srv_id, ('/%s' % cmd if cmd else ''))
273

    
274
            if json_data:
275
                json_data = dumps(json_data)
276
                self.assertEqual(set_headers.mock_calls[-2:], [
277
                    call('Content-Type', 'application/json'),
278
                    call('Content-Length', len(json_data))])
279
            self.assertEqual(
280
                put.mock_calls[-1],
281
                call(srv_str, data=json_data, **kwargs))
282

    
283
            param_calls = []
284
            for k, v in params.items():
285
                real_v = srv_kwargs.get(k, v[1])
286
                param_calls.append(call(v[0], real_v, iff=real_v))
287
            actual = set_param.mock_calls[- len(param_calls):]
288
            self.assertEqual(sorted(actual), sorted(param_calls))
289

    
290
            num_of_its = print_iterations(num_of_its, i)
291
        print ('\b' * len('%s' % num_of_its)) + ('%s' % i)
292

    
293
    @patch('%s.delete' % rest_pkg, return_value=FR())
294
    def _test_delete(self, srv, cmd, delete):
295
        method = getattr(
296
            self.client, '%s_%sdelete' % (srv, ('%s_' % cmd) if cmd else ''))
297
        cmd_params = ('some_cmd_value', 'some_other_value') if cmd else ()
298
        num_of_its = 0
299
        for i, args in enumerate(product(
300
                ('%s_id' % srv, 'some_value'),
301
                (204, 208),
302
                ({}, {'k': 'v'}),
303
                *cmd_params)):
304
            (srv_id, success, kwargs) = args[:3]
305
            kwargs = dict(kwargs)
306
            kwargs['success'] = success
307
            cmd_value = args[-1] if cmd else ''
308
            method_args = (srv_id, cmd_value) if cmd else (srv_id, )
309
            method(*method_args, **kwargs)
310
            srv_str = '/%s/%s' % (srv, srv_id)
311
            cmd_str = ('/%s/%s' % (cmd, cmd_value)) if cmd else ''
312
            self.assertEqual(
313
                delete.mock_calls[-1],
314
                call('%s%s' % (srv_str, cmd_str), **kwargs))
315
            num_of_its = print_iterations(num_of_its, i)
316
        print ('\b' * len('%s' % num_of_its)) + ('%s' % i)
317

    
318
    @patch('%s.get' % rest_pkg, return_value=FR())
319
    def test_limits_get(self, get):
320
        self.client.limits_get(success='some_val')
321
        get.assert_called_once_with('/limits', success='some_val')
322

    
323
    def test_servers_get(self):
324
        params = dict(
325
            changes_since=('changes-since', None),
326
            image=('image', None),
327
            flavor=('flavor', None),
328
            name=('name', None),
329
            marker=('marker', None),
330
            limit=('limit', None),
331
            status=('status', None),
332
            host=('host', None))
333
        self._test_get('servers', params)
334

    
335
    def test_servers_post(self):
336
        params = dict(
337
            security_group=('security_group', None),
338
            user_data=('user_data', None),
339
            availability_zone=('availability_zone', None))
340
        self._test_post('servers', None, params)
341

    
342
    def test_servers_put(self):
343
        self._test_put('servers', None, dict(server_name=('server', None)))
344

    
345
    def test_servers_delete(self):
346
        self._test_delete('servers', None)
347

    
348
    def test_servers_metadata_get(self):
349
        self._test_srv_cmd_get('servers', 'metadata', {})
350

    
351
    def test_servers_metadata_post(self):
352
        self._test_post('servers', 'metadata', {})
353

    
354
    def test_servers_metadata_put(self):
355
        self._test_put('servers', 'metadata', {})
356

    
357
    def test_images_metadata_delete(self):
358
        self._test_delete('images', 'metadata')
359

    
360
    def test_servers_action_post(self):
361
        self._test_post('servers', 'action', {})
362

    
363
    def test_servers_ips_get(self):
364
        params = dict(changes_since=('changes-since', None))
365
        self._test_srv_cmd_get('servers', 'ips', params)
366

    
367
    def test_images_get(self):
368
        param = dict(
369
            changes_since=('changes-since', None),
370
            server_name=('server', None),
371
            name=('name', None),
372
            status=('status', None),
373
            marker=('marker', None),
374
            limit=('limit', None),
375
            type=('type', None))
376
        self._test_get('images', param)
377

    
378
    def test_images_delete(self):
379
        self._test_delete('images', None)
380

    
381
    def test_images_metadata_get(self):
382
        self._test_srv_cmd_get('images', 'metadata', {})
383

    
384
    def test_images_metadata_post(self):
385
        self._test_post('images', 'metadata', {})
386

    
387
    def test_images_metadata_put(self):
388
        self._test_put('images', 'metadata', {})
389

    
390
    def test_servers_metadata_delete(self):
391
        self._test_delete('servers', 'metadata')
392

    
393
    def test_flavors_get(self):
394
        params = dict(
395
            changes_since=('changes-since', None),
396
            minDisk=('minDisk', None),
397
            minRam=('minRam', None),
398
            marker=('marker', None),
399
            limit=('limit', None))
400
        self._test_get('flavors', params)
401

    
402
    @patch('%s.get' % rest_pkg, return_value=FR())
403
    def test_floating_ip_pools_get(self, get):
404
        for args in product(
405
                (200, 204),
406
                ({}, {'k': 'v'})):
407
            success, kwargs = args
408
            r = self.client.floating_ip_pools_get(success, **kwargs)
409
            self.assertTrue(isinstance(r, FR))
410
            self.assertEqual(get.mock_calls[-1], call(
411
                '/os-floating-ip-pools', success=success, **kwargs))
412

    
413
    @patch('%s.get' % rest_pkg, return_value=FR())
414
    def test_floating_ips_get(self, get):
415
        for args in product(
416
                ('', '192.193.194.195'),
417
                (200, 204),
418
                ({}, {'k': 'v'})):
419
            ip, success, kwargs = args
420
            r = self.client.floating_ips_get(*args[:2], **kwargs)
421
            self.assertTrue(isinstance(r, FR))
422
            expected = '' if not ip else '/%s' % ip
423
            self.assertEqual(get.mock_calls[-1], call(
424
                '/os-floating-ips%s' % expected, success=success, **kwargs))
425

    
426
    @patch('%s.set_header' % rest_pkg)
427
    @patch('%s.post' % rest_pkg, return_value=FR())
428
    def test_floating_ips_post(self, post, SH):
429
        for args in product(
430
                (None, [dict(json="data"), dict(data="json")]),
431
                ('', '192.193.194.195'),
432
                (202, 204),
433
                ({}, {'k': 'v'})):
434
            json_data, ip, success, kwargs = args
435
            self.client.floating_ips_post(*args[:3], **kwargs)
436
            if json_data:
437
                json_data = dumps(json_data)
438
                self.assertEqual(SH.mock_calls[-2:], [
439
                    call('Content-Type', 'application/json'),
440
                    call('Content-Length', len(json_data))])
441
            expected = '' if not ip else '/%s' % ip
442
            self.assertEqual(post.mock_calls[-1], call(
443
                '/os-floating-ips%s' % expected,
444
                data=json_data, success=success,
445
                **kwargs))
446

    
447
    @patch('%s.delete' % rest_pkg, return_value=FR())
448
    def test_floating_ips_delete(self, delete):
449
        for args in product(
450
                ('', '192.193.194.195'),
451
                (204,),
452
                ({}, {'k': 'v'})):
453
            ip, success, kwargs = args
454
            r = self.client.floating_ips_delete(*args[:2], **kwargs)
455
            self.assertTrue(isinstance(r, FR))
456
            expected = '' if not ip else '/%s' % ip
457
            self.assertEqual(delete.mock_calls[-1], call(
458
                '/os-floating-ips%s' % expected, success=success, **kwargs))
459

    
460

    
461
class ComputeClient(TestCase):
462

    
463
    def assert_dicts_are_equal(self, d1, d2):
464
        for k, v in d1.items():
465
            self.assertTrue(k in d2)
466
            if isinstance(v, dict):
467
                self.assert_dicts_are_equal(v, d2[k])
468
            else:
469
                self.assertEqual(unicode(v), unicode(d2[k]))
470

    
471
    """Set up a Cyclades thorough test"""
472
    def setUp(self):
473
        self.url = 'http://cyclades.example.com'
474
        self.token = 'cyc14d3s70k3n'
475
        self.client = compute.ComputeClient(self.url, self.token)
476

    
477
    def tearDown(self):
478
        FR.status_code = 200
479
        FR.json = vm_recv
480

    
481
    def test_create_server(self):
482
        with patch.object(
483
                compute.ComputeClient, 'servers_post',
484
                side_effect=ClientError(
485
                    'REQUEST ENTITY TOO LARGE',
486
                    status=403)):
487
            self.assertRaises(
488
                ClientError,
489
                self.client.create_server,
490
                vm_name, fid, img_ref)
491

    
492
        for params in product(
493
                ('security_group', None),
494
                ('user_data', None),
495
                ('availability_zone', None),
496
                (None, {'os': 'debian', 'users': 'root'})):
497
            kwargs = dict()
498
            for i, k in enumerate((
499
                    'security_group', 'user_data', 'availability_zone')):
500
                if params[i]:
501
                    kwargs[k] = params[i]
502
            with patch.object(
503
                    compute.ComputeClient, 'servers_post',
504
                    return_value=FR()) as post:
505
                r = self.client.create_server(vm_name, fid, img_ref, **kwargs)
506
                self.assertEqual(r, FR.json['server'])
507
                exp_json = dict(server=dict(
508
                    flavorRef=fid, name=vm_name, imageRef=img_ref))
509
                for k in set([
510
                        'security_group',
511
                        'user_data',
512
                        'availability_zone']).difference(kwargs):
513
                    kwargs[k] = None
514
                self.assertEqual(
515
                    post.mock_calls[-1], call(json_data=exp_json, **kwargs))
516
                prsn = 'Personality string (does not work with real servers)'
517
                self.client.create_server(
518
                    vm_name, fid, img_ref, personality=prsn, **kwargs)
519
                exp_json['server']['personality'] = prsn
520
                self.assertEqual(
521
                    post.mock_calls[-1], call(json_data=exp_json, **kwargs))
522
                kwargs.pop('personality', None)
523
                exp_json['server'].pop('personality', None)
524
                mtdt = 'Metadata dict here'
525
                self.client.create_server(
526
                    vm_name, fid, img_ref, metadata=mtdt, **kwargs)
527
                exp_json['server']['metadata'] = mtdt
528
                self.assertEqual(
529
                    post.mock_calls[-1], call(json_data=exp_json, **kwargs))
530

    
531
    @patch('%s.servers_get' % compute_pkg, return_value=FR())
532
    def test_list_servers(self, SG):
533
        FR.json = vm_list
534
        for args in product(
535
                (False, True),
536
                ({}, dict(status='status')),
537
                ({}, dict(name='name')),
538
                ({}, dict(image='image')),
539
                ({}, dict(flavor='flavor')),
540
                ({}, dict(host='host')),
541
                ({}, dict(limit='limit')),
542
                ({}, dict(marker='marker')),
543
                ({}, dict(changes_since='changes_since'))):
544
            detail = args[0]
545
            kwargs = dict()
546
            for param in args[1:]:
547
                kwargs.update(param)
548
            r = self.client.list_servers(detail, **kwargs)
549
            for k in set([
550
                    'status', 'name',
551
                    'image', 'flavor',
552
                    'host', 'limit',
553
                    'marker', 'changes_since']).difference(kwargs):
554
                kwargs[k] = None
555
            self.assertEqual(SG.mock_calls[-1], call(detail=detail, **kwargs))
556
            for i, vm in enumerate(vm_list['servers']):
557
                self.assert_dicts_are_equal(r[i], vm)
558
            self.assertEqual(i + 1, len(r))
559

    
560
    @patch('%s.servers_get' % compute_pkg, return_value=FR())
561
    def test_get_server_details(self, SG):
562
        vm_id = vm_recv['server']['id']
563
        for args in product(
564
                ({}, dict(status='status')),
565
                ({}, dict(name='name')),
566
                ({}, dict(image='image')),
567
                ({}, dict(flavor='flavor')),
568
                ({}, dict(host='host')),
569
                ({}, dict(limit='limit')),
570
                ({}, dict(marker='marker')),
571
                ({}, dict(changes_since='changes_since'))):
572
            kwargs = dict()
573
            for param in args:
574
                kwargs.update(param)
575
            r = self.client.get_server_details(vm_id, **kwargs)
576
            for k in set([
577
                    'status', 'name',
578
                    'image', 'flavor',
579
                    'host', 'limit',
580
                    'marker', 'changes_since']).difference(kwargs):
581
                kwargs[k] = None
582
            self.assertEqual(SG.mock_calls[-1], call(vm_id, **kwargs))
583
            self.assert_dicts_are_equal(r, vm_recv['server'])
584

    
585
    @patch('%s.servers_put' % compute_pkg, return_value=FR())
586
    def test_update_server_name(self, SP):
587
        vm_id = vm_recv['server']['id']
588
        new_name = vm_name + '_new'
589
        self.client.update_server_name(vm_id, new_name)
590
        SP.assert_called_once_with(vm_id, json_data=dict(
591
            server=dict(name=new_name)))
592

    
593
    @patch('%s.servers_action_post' % compute_pkg, return_value=FR())
594
    def test_reboot_server(self, SP):
595
        vm_id = vm_recv['server']['id']
596
        for hard in (None, True):
597
            self.client.reboot_server(vm_id, hard=hard)
598
            self.assertEqual(SP.mock_calls[-1], call(vm_id, json_data=dict(
599
                reboot=dict(type='HARD' if hard else 'SOFT'))))
600

    
601
    @patch('%s.servers_action_post' % compute_pkg, return_value=FR())
602
    def test_resize_server(self, SP):
603
        vm_id, flavor = vm_recv['server']['id'], flavor_list['flavors'][1]
604
        self.client.resize_server(vm_id, flavor['id'])
605
        exp = dict(resize=dict(flavorRef=flavor['id']))
606
        SP.assert_called_once_with(vm_id, json_data=exp)
607

    
608
    @patch('%s.servers_metadata_put' % compute_pkg, return_value=FR())
609
    def test_create_server_metadata(self, SP):
610
        vm_id = vm_recv['server']['id']
611
        metadata = dict(m1='v1', m2='v2', m3='v3')
612
        FR.json = dict(meta=vm_recv['server'])
613
        for k, v in metadata.items():
614
            r = self.client.create_server_metadata(vm_id, k, v)
615
            self.assert_dicts_are_equal(r, vm_recv['server'])
616
            self.assertEqual(SP.mock_calls[-1], call(
617
                vm_id, '%s' % k,
618
                json_data=dict(meta={k: v}), success=201))
619

    
620
    @patch('%s.servers_metadata_get' % compute_pkg, return_value=FR())
621
    def test_get_server_metadata(self, SG):
622
        vm_id = vm_recv['server']['id']
623
        metadata = dict(m1='v1', m2='v2', m3='v3')
624
        FR.json = dict(metadata=metadata)
625
        r = self.client.get_server_metadata(vm_id)
626
        FR.json = dict(meta=metadata)
627
        SG.assert_called_once_with(vm_id, '')
628
        self.assert_dicts_are_equal(r, metadata)
629

    
630
        for k, v in metadata.items():
631
            FR.json = dict(meta={k: v})
632
            r = self.client.get_server_metadata(vm_id, k)
633
            self.assert_dicts_are_equal(r, {k: v})
634
            self.assertEqual(
635
                SG.mock_calls[-1], call(vm_id, '%s' % k))
636

    
637
    @patch('%s.servers_metadata_post' % compute_pkg, return_value=FR())
638
    def test_update_server_metadata(self, SP):
639
        vm_id = vm_recv['server']['id']
640
        metadata = dict(m1='v1', m2='v2', m3='v3')
641
        FR.json = dict(metadata=metadata)
642
        r = self.client.update_server_metadata(vm_id, **metadata)
643
        self.assert_dicts_are_equal(r, metadata)
644
        SP.assert_called_once_with(
645
            vm_id, json_data=dict(metadata=metadata), success=201)
646

    
647
    @patch('%s.servers_metadata_delete' % compute_pkg, return_value=FR())
648
    def test_delete_server_metadata(self, SD):
649
        vm_id = vm_recv['server']['id']
650
        key = 'metakey'
651
        self.client.delete_server_metadata(vm_id, key)
652
        SD.assert_called_once_with(vm_id, key)
653

    
654
    @patch('%s.flavors_get' % compute_pkg, return_value=FR())
655
    def test_list_flavors(self, FG):
656
        FR.json = flavor_list
657
        for detail in ('', 'detail'):
658
            r = self.client.list_flavors(detail=bool(detail))
659
            self.assertEqual(FG.mock_calls[-1], call(detail=bool(detail)))
660
            self.assertEqual(r, flavor_list['flavors'])
661

    
662
    @patch('%s.flavors_get' % compute_pkg, return_value=FR())
663
    def test_get_flavor_details(self, FG):
664
        FR.json = dict(flavor=flavor_list['flavors'][0])
665
        r = self.client.get_flavor_details(fid)
666
        FG.assert_called_once_with(fid)
667
        self.assert_dicts_are_equal(r, flavor_list['flavors'][0])
668

    
669
    @patch('%s.images_get' % compute_pkg, return_value=FR())
670
    def test_list_images(self, IG):
671
        FR.json = img_list
672
        for detail in ('', 'detail'):
673
            r = self.client.list_images(detail=detail)
674
            self.assertEqual(IG.mock_calls[-1], call(detail=bool(detail)))
675
            expected = img_list['images']
676
            for i in range(len(r)):
677
                self.assert_dicts_are_equal(expected[i], r[i])
678

    
679
    @patch('%s.images_get' % compute_pkg, return_value=FR())
680
    def test_get_image_details(self, IG):
681
        FR.json = img_recv
682
        r = self.client.get_image_details(img_ref)
683
        IG.assert_called_once_with(img_ref)
684
        self.assert_dicts_are_equal(r, img_recv['image'])
685

    
686
    @patch('%s.images_metadata_get' % compute_pkg, return_value=FR())
687
    def test_get_image_metadata(self, IG):
688
        for key in ('', '50m3k3y'):
689
            FR.json = dict(meta=img_recv['image']) if (
690
                key) else dict(metadata=img_recv['image'])
691
            r = self.client.get_image_metadata(img_ref, key)
692
            self.assertEqual(IG.mock_calls[-1], call(img_ref, key or ''))
693
            self.assert_dicts_are_equal(img_recv['image'], r)
694

    
695
    @patch('%s.servers_delete' % compute_pkg, return_value=FR())
696
    def test_delete_server(self, SD):
697
        vm_id = vm_recv['server']['id']
698
        self.client.delete_server(vm_id)
699
        SD.assert_called_once_with(vm_id)
700

    
701
    @patch('%s.images_delete' % compute_pkg, return_value=FR())
702
    def test_delete_image(self, ID):
703
        self.client.delete_image(img_ref)
704
        ID.assert_called_once_with(img_ref)
705

    
706
    # @patch('%s.images_metadata_put' % compute_pkg, return_value=FR())
707
    # def test_create_image_metadata(self, IP):
708
    #     (key, val) = ('k1', 'v1')
709
    #     FR.json = dict(meta=img_recv['image'])
710
    #     r = self.client.create_image_metadata(img_ref, key, val)
711
    #     IP.assert_called_once_with(
712
    #         img_ref, '%s' % key,
713
    #         json_data=dict(meta={key: val}))
714
    #     self.assert_dicts_are_equal(r, img_recv['image'])
715

    
716
    @patch('%s.images_metadata_post' % compute_pkg, return_value=FR())
717
    def test_update_image_metadata(self, IP):
718
        metadata = dict(m1='v1', m2='v2', m3='v3')
719
        FR.json = dict(metadata=metadata)
720
        r = self.client.update_image_metadata(img_ref, **metadata)
721
        IP.assert_called_once_with(
722
            img_ref, json_data=dict(metadata=metadata))
723
        self.assert_dicts_are_equal(r, metadata)
724

    
725
    @patch('%s.images_metadata_delete' % compute_pkg, return_value=FR())
726
    def test_delete_image_metadata(self, ID):
727
        key = 'metakey'
728
        self.client.delete_image_metadata(img_ref, key)
729
        ID.assert_called_once_with(img_ref, '%s' % key)
730

    
731
    @patch('%s.floating_ip_pools_get' % compute_pkg, return_value=FR())
732
    def test_get_floating_ip_pools(self, get):
733
        tid = 't3n@nt_1d'
734
        r = self.client.get_floating_ip_pools(tid)
735
        self.assert_dicts_are_equal(r, FR.json)
736
        self.assertEqual(get.mock_calls[-1], call(tid))
737

    
738
    @patch('%s.floating_ips_get' % compute_pkg, return_value=FR())
739
    def test_get_floating_ips(self, get):
740
        tid = 't3n@nt_1d'
741
        r = self.client.get_floating_ips(tid)
742
        self.assert_dicts_are_equal(r, FR.json)
743
        self.assertEqual(get.mock_calls[-1], call(tid))
744

    
745
    @patch('%s.floating_ips_post' % compute_pkg, return_value=FR())
746
    def test_alloc_floating_ip(self, post):
747
        FR.json = dict(floating_ip=dict(
748
            fixed_ip='fip',
749
            id=1,
750
            instance_id='lala',
751
            ip='102.0.0.1',
752
            pool='pisine'))
753
        for args in product(
754
                ('t1', 't2'),
755
                (None, 'pisine')):
756
            r = self.client.alloc_floating_ip(*args)
757
            tenant_id, pool = args
758
            self.assert_dicts_are_equal(r, FR.json['floating_ip'])
759
            expected = dict(pool=pool) if pool else dict()
760
            self.assertEqual(post.mock_calls[-1], call(tenant_id, expected))
761

    
762
    @patch('%s.floating_ips_get' % compute_pkg, return_value=FR())
763
    def test_get_floating_ip(self, get):
764
        FR.json = dict(floating_ips=[dict(
765
            fixed_ip='fip',
766
            id=1,
767
            instance_id='lala',
768
            ip='102.0.0.1',
769
            pool='pisine'), ])
770
        for args in product(
771
                ('t1', 't2'),
772
                (None, 'fip')):
773
            r = self.client.get_floating_ip(*args)
774
            tenant_id, fip = args
775
            self.assertEqual(r, FR.json['floating_ips'])
776
            self.assertEqual(get.mock_calls[-1], call(tenant_id, fip))
777

    
778
    @patch('%s.floating_ips_delete' % compute_pkg, return_value=FR())
779
    def test_delete_floating_ip(self, delete):
780
        for args in product(
781
                ('t1', 't2'),
782
                (None, 'fip')):
783
            r = self.client.delete_floating_ip(*args)
784
            tenant_id, fip = args
785
            self.assertEqual(r, FR.headers)
786
            self.assertEqual(delete.mock_calls[-1], call(tenant_id, fip))
787

    
788

    
789
if __name__ == '__main__':
790
    from sys import argv
791
    from kamaki.clients.test import runTestCase
792
    not_found = True
793
    if not argv[1:] or argv[1] == 'ComputeClient':
794
        not_found = False
795
        runTestCase(ComputeClient, 'Compute Client', argv[2:])
796
    if not argv[1:] or argv[1] == 'ComputeRest':
797
        not_found = False
798
        runTestCase(ComputeRestClient, 'ComputeRest Client', argv[2:])
799
    if not_found:
800
        print('TestCase %s not found' % argv[1])