Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (24.9 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, Mock, call
35
from unittest import TestCase
36
from json import loads
37

    
38
from kamaki.clients import Client, ClientError
39
from kamaki.clients.cyclades import CycladesClient
40
from kamaki.clients.cyclades_rest_api import CycladesClientApi
41

    
42

    
43
khttp_pkg = 'kamaki.clients.connection.kamakicon.KamakiHTTPConnection'
44
compute_pkg = 'kamaki.clients.cyclades.CycladesClient'
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(values=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(values=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=dict(values=[
85
    dict(name='n1', id=1),
86
    dict(name='n2', id=2)]))
87
flavor_list = dict(flavors=dict(values=[
88
        dict(id=41, name="C1R1024D20"),
89
        dict(id=42, name="C1R1024D40"),
90
        dict(id=43, name="C1R1028D20")]))
91
img_list = dict(images=dict(values=[
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
net_send = dict(network=dict(dhcp=False, name='someNet'))
101
net_recv = dict(network=dict(
102
    status="PENDING",
103
    updated="2013-03-05T15:04:51.758780+00:00",
104
    name="someNet",
105
    created="2013-03-05T15:04:51.758728+00:00",
106
    cidr6=None,
107
    id="2130",
108
    gateway6=None,
109
    public=False,
110
    dhcp=False,
111
    cidr="192.168.1.0/24",
112
    type="MAC_FILTERED",
113
    gateway=None,
114
    attachments=dict(values=[dict(name='att1'), dict(name='att2')])))
115
net_list = dict(networks=dict(values=[
116
    dict(id=1, name='n1'),
117
    dict(id=2, name='n2'),
118
    dict(id=3, name='n3')]))
119

    
120

    
121
class FR(object):
122
    """FR stands for Fake Response"""
123
    json = vm_recv
124
    headers = {}
125
    content = json
126
    status = None
127
    status_code = 200
128

    
129
    def release(self):
130
        pass
131

    
132

    
133
class Cyclades(TestCase):
134

    
135
    def assert_dicts_are_equal(self, d1, d2):
136
        for k, v in d1.items():
137
            self.assertTrue(k in d2)
138
            if isinstance(v, dict):
139
                self.assert_dicts_are_equal(v, d2[k])
140
            else:
141
                self.assertEqual(unicode(v), unicode(d2[k]))
142

    
143
    """Set up a Cyclades thorough test"""
144
    def setUp(self):
145
        self.url = 'http://cyclades.example.com'
146
        self.token = 'cyc14d3s70k3n'
147
        self.client = CycladesClient(self.url, self.token)
148
        from kamaki.clients.connection.kamakicon import KamakiHTTPConnection
149
        self.C = KamakiHTTPConnection
150

    
151
    def tearDown(self):
152
        FR.status_code = 200
153
        FR.json = vm_recv
154

    
155
    @patch(
156
        '%s.get_image_details' % compute_pkg,
157
        return_value=img_recv['image'])
158
    def test_create_server(self, GID):
159
        with patch.object(
160
                CycladesClient, 'servers_post',
161
                side_effect=ClientError(
162
                    'REQUEST ENTITY TOO LARGE',
163
                    status=403)):
164
            self.assertRaises(
165
                ClientError,
166
                self.client.create_server,
167
                vm_name, fid, img_ref)
168
        self.assertEqual(GID.mock_calls[-1], call(img_ref))
169

    
170
        with patch.object(
171
                CycladesClient, 'servers_post',
172
                return_value=FR()) as post:
173
            r = self.client.create_server(vm_name, fid, img_ref)
174
            self.assertEqual(r, FR.json['server'])
175
            self.assertEqual(GID.mock_calls[-1], call(img_ref))
176
            self.assertEqual(post.mock_calls[-1], call(json_data=vm_send))
177
            prsn = 'Personality string (does not work with real servers)'
178
            self.client.create_server(vm_name, fid, img_ref, prsn)
179
            expected = dict(server=dict(vm_send['server']))
180
            expected['server']['personality'] = prsn
181
            self.assertEqual(post.mock_calls[-1], call(json_data=expected))
182

    
183
    @patch('%s.servers_get' % compute_pkg, return_value=FR())
184
    def test_list_servers(self, SG):
185
        FR.json = vm_list
186
        for detail in (False, True):
187
            r = self.client.list_servers(detail)
188
            for i, vm in enumerate(vm_list['servers']['values']):
189
                self.assert_dicts_are_equal(r[i], vm)
190
            self.assertEqual(i + 1, len(r))
191
            self.assertEqual(SG.mock_calls[-1], call(
192
                changes_since=None,
193
                command='detail' if detail else ''))
194

    
195
    @patch('%s.servers_get' % compute_pkg, return_value=FR())
196
    def test_get_server_details(self, SG):
197
        vm_id = vm_recv['server']['id']
198
        r = self.client.get_server_details(vm_id)
199
        self.assert_dicts_are_equal(r, vm_recv['server'])
200
        self.assertEqual(SG.mock_calls[-1], call(vm_id))
201

    
202
    @patch('%s.servers_put' % compute_pkg, return_value=FR())
203
    def test_update_server_name(self, SP):
204
        vm_id = vm_recv['server']['id']
205
        new_name = vm_name + '_new'
206
        self.client.update_server_name(vm_id, new_name)
207
        self.assertEqual(SP.mock_calls[-1], call(vm_id, json_data=dict(
208
            server=dict(name=new_name))))
209

    
210
    @patch('%s.servers_post' % compute_pkg, return_value=FR())
211
    def test_reboot_server(self, SP):
212
        vm_id = vm_recv['server']['id']
213
        for hard in (None, True):
214
            self.client.reboot_server(vm_id, hard=hard)
215
            self.assertEqual(SP.mock_calls[-1], call(
216
                vm_id, 'action',
217
                json_data=dict(reboot=dict(type='HARD' if hard else 'SOFT'))))
218

    
219
    @patch('%s.servers_put' % compute_pkg, return_value=FR())
220
    def test_create_server_metadata(self, SP):
221
        vm_id = vm_recv['server']['id']
222
        metadata = dict(m1='v1', m2='v2', m3='v3')
223
        FR.json = dict(meta=vm_recv['server'])
224
        for k, v in metadata.items():
225
            r = self.client.create_server_metadata(vm_id, k, v)
226
            self.assert_dicts_are_equal(r, vm_recv['server'])
227
            self.assertEqual(SP.mock_calls[-1], call(
228
                vm_id, 'meta/%s' % k,
229
                json_data=dict(meta={k: v}), success=201))
230

    
231
    """
232
    @patch('%s.perform_request' % khttp, return_value=FR())
233
    def test_get_server_metadata(self, PR):
234
        vm_id = vm_recv['server']['id']
235
        metadata = dict(m1='v1', m2='v2', m3='v3')
236
        FR.json = dict(metadata=dict(values=metadata))
237
        r = self.client.get_server_metadata(vm_id)
238
        self.assertEqual(self.client.http_client.url, self.url)
239
        self.assertEqual(
240
            self.client.http_client.path,
241
            '/servers/%s/meta' % vm_id)
242
        self.assert_dicts_are_equal(r, metadata)
243

244
        for k, v in metadata.items():
245
            FR.json = dict(meta={k: v})
246
            r = self.client.get_server_metadata(vm_id, k)
247
            self.assertEqual(self.client.http_client.url, self.url)
248
            self.assertEqual(
249
                self.client.http_client.path,
250
                '/servers/%s/meta/%s' % (vm_id, k))
251
            self.assert_dicts_are_equal(r, {k: v})
252

253
    @patch('%s.servers_post' % cyclades_pkg, return_value=FR())
254
    def test_update_server_metadata(self, servers_post):
255
        vm_id = vm_recv['server']['id']
256
        metadata = dict(m1='v1', m2='v2', m3='v3')
257
        FR.json = dict(metadata=metadata)
258
        r = self.client.update_server_metadata(vm_id, **metadata)
259
        self.assert_dicts_are_equal(r, metadata)
260
        (called_id, cmd) = servers_post.call_args[0]
261
        self.assertEqual(called_id, vm_id)
262
        self.assertEqual(cmd, 'meta')
263
        data = servers_post.call_args[1]['json_data']
264
        self.assert_dicts_are_equal(data, dict(metadata=metadata))
265

266
    @patch('%s.servers_delete' % cyclades_pkg, return_value=FR())
267
    def test_delete_server_metadata(self, servers_delete):
268
        vm_id = vm_recv['server']['id']
269
        key = 'metakey'
270
        self.client.delete_server_metadata(vm_id, key)
271
        self.assertEqual((vm_id, 'meta/' + key), servers_delete.call_args[0])
272

273
    @patch('%s.perform_request' % khttp, return_value=FR())
274
    def test_list_flavors(self, PR):
275
        FR.json = flavor_list
276
        r = self.client.list_flavors()
277
        self.assertEqual(self.client.http_client.url, self.url)
278
        self.assertEqual(self.client.http_client.path, '/flavors')
279
        (method, data, a_headers, a_params) = PR.call_args[0]
280
        self.assert_dicts_are_equal(dict(values=r), flavor_list['flavors'])
281
        r = self.client.list_flavors(detail=True)
282
        self.assertEqual(self.client.http_client.url, self.url)
283
        self.assertEqual(self.client.http_client.path, '/flavors/detail')
284

285
    @patch('%s.perform_request' % khttp, return_value=FR())
286
    def test_get_flavor_details(self, PR):
287
        FR.json = dict(flavor=flavor_list['flavors'])
288
        r = self.client.get_flavor_details(fid)
289
        self.assertEqual(self.client.http_client.url, self.url)
290
        self.assertEqual(self.client.http_client.path, '/flavors/%s' % fid)
291
        self.assert_dicts_are_equal(r, flavor_list['flavors'])
292

293
    @patch('%s.perform_request' % khttp, return_value=FR())
294
    def test_list_images(self, PR):
295
        FR.json = img_list
296
        r = self.client.list_images()
297
        self.assertEqual(self.client.http_client.url, self.url)
298
        self.assertEqual(self.client.http_client.path, '/images')
299
        expected = img_list['images']['values']
300
        for i in range(len(r)):
301
            self.assert_dicts_are_equal(expected[i], r[i])
302
        self.client.list_images(detail=True)
303
        self.assertEqual(self.client.http_client.url, self.url)
304
        self.assertEqual(self.client.http_client.path, '/images/detail')
305

306
    @patch('%s.perform_request' % khttp, return_value=FR())
307
    def test_get_image_details(self, PR):
308
        FR.json = img_recv
309
        r = self.client.get_image_details(img_ref)
310
        self.assertEqual(self.client.http_client.url, self.url)
311
        self.assertEqual(self.client.http_client.path, '/images/%s' % img_ref)
312
        self.assert_dicts_are_equal(r, img_recv['image'])
313

314
    @patch('%s.images_get' % cyclades_pkg, return_value=FR())
315
    def test_get_image_metadata(self, IG):
316
        FR.json = dict(metadata=dict(values=img_recv['image']))
317
        r = self.client.get_image_metadata(img_ref)
318
        self.assertEqual(IG.call_args[0], ('%s' % img_ref, '/meta'))
319
        self.assert_dicts_are_equal(img_recv['image'], r)
320
        FR.json = dict(meta=img_recv['image'])
321
        key = 'somekey'
322
        self.client.get_image_metadata(img_ref, key)
323
        self.assertEqual(IG.call_args[0], ('%s' % img_ref, '/meta/%s' % key))
324

325
    @patch('%s.perform_request' % khttp, return_value=FR())
326
    def test_shutdown_server(self, PR):
327
        vm_id = vm_recv['server']['id']
328
        FR.status_code = 202
329
        self.client.shutdown_server(vm_id)
330
        self.assertEqual(self.client.http_client.url, self.url)
331
        self.assertEqual(
332
            self.client.http_client.path,
333
            '/servers/%s/action' % vm_id)
334
        self.assertEqual(
335
            PR.call_args[0],
336
            ('post',  '{"shutdown": {}}', {}, {}))
337

338
    @patch('%s.perform_request' % khttp, return_value=FR())
339
    def test_start_server(self, PR):
340
        vm_id = vm_recv['server']['id']
341
        FR.status_code = 202
342
        self.client.start_server(vm_id)
343
        self.assertEqual(self.client.http_client.url, self.url)
344
        self.assertEqual(
345
            self.client.http_client.path,
346
            '/servers/%s/action' % vm_id)
347
        self.assertEqual(PR.call_args[0], ('post',  '{"start": {}}', {}, {}))
348

349
    @patch('%s.perform_request' % khttp, return_value=FR())
350
    def test_get_server_console(self, PR):
351
        cnsl = dict(console=dict(info1='i1', info2='i2', info3='i3'))
352
        FR.json = cnsl
353
        vm_id = vm_recv['server']['id']
354
        r = self.client.get_server_console(vm_id)
355
        self.assertEqual(self.client.http_client.url, self.url)
356
        self.assertEqual(
357
            self.client.http_client.path,
358
            '/servers/%s/action' % vm_id)
359
        self.assert_dicts_are_equal(cnsl['console'], r)
360
        self.assertEqual(
361
            PR.call_args[0],
362
            ('post',  '{"console": {"type": "vnc"}}', {}, {}))
363

364
    def test_get_firewall_profile(self):
365
        vm_id = vm_recv['server']['id']
366
        v = 'Some profile'
367
        ret = {'attachments': {'values': [{'firewallProfile': v, 1:1}]}}
368
        with patch.object(
369
                CycladesClient,
370
                'get_server_details',
371
                return_value=ret) as GSD:
372
            r = self.client.get_firewall_profile(vm_id)
373
            self.assertEqual(r, v)
374
            self.assertEqual(GSD.call_args[0], (vm_id,))
375
            ret['attachments']['values'][0].pop('firewallProfile')
376
            self.assertRaises(
377
                ClientError,
378
                self.client.get_firewall_profile,
379
                vm_id)
380

381
    @patch('%s.perform_request' % khttp, return_value=FR())
382
    def test_set_firewall_profile(self, PR):
383
        vm_id = vm_recv['server']['id']
384
        v = 'Some profile'
385
        FR.status_code = 202
386
        self.client.set_firewall_profile(vm_id, v)
387
        self.assertEqual(self.client.http_client.url, self.url)
388
        self.assertEqual(
389
            self.client.http_client.path,
390
            '/servers/%s/action' % vm_id)
391
        self.assertEqual(PR.call_args[0], (
392
            'post',
393
            '{"firewallProfile": {"profile": "%s"}}' % v,
394
            {},
395
            {}))
396

397
    @patch('%s.perform_request' % khttp, return_value=FR())
398
    def test_get_server_stats(self, PR):
399
        vm_id = vm_recv['server']['id']
400
        stats = dict(stat1='v1', stat2='v2', stat3='v3', stat4='v4')
401
        FR.json = dict(stats=stats)
402
        r = self.client.get_server_stats(vm_id)
403
        self.assertEqual(self.client.http_client.url, self.url)
404
        self.assertEqual(
405
            self.client.http_client.path,
406
            '/servers/%s/stats' % vm_id)
407
        self.assert_dicts_are_equal(stats, r)
408

409
    @patch('%s.perform_request' % khttp, return_value=FR())
410
    def test_create_network(self, PR):
411
        net_name = net_send['network']['name']
412
        FR.json = net_recv
413
        FR.status_code = 202
414
        full_args = dict(
415
                cidr='192.168.0.0/24',
416
                gateway='192.168.0.1',
417
                type='MAC_FILTERED',
418
                dhcp=True)
419
        test_args = dict(full_args)
420
        test_args.update(dict(empty=None, full=None))
421
        for arg, val in test_args.items():
422
            kwargs = {} if arg == 'empty' else full_args if (
423
                arg == 'full') else {arg: val}
424
            r = self.client.create_network(net_name, **kwargs)
425
            self.assertEqual(self.client.http_client.url, self.url)
426
            self.assertEqual(
427
                self.client.http_client.path,
428
                '/networks')
429
            self.assert_dicts_are_equal(r, net_recv['network'])
430
            data = PR.call_args[0][1]
431
            expected = dict(network=dict(net_send['network']))
432
            expected['network'].update(kwargs)
433
            self.assert_dicts_are_equal(loads(data), expected)
434

435
    @patch('%s.perform_request' % khttp, return_value=FR())
436
    def test_connect_server(self, PR):
437
        vm_id = vm_recv['server']['id']
438
        net_id = net_recv['network']['id']
439
        FR.status_code = 202
440
        self.client.connect_server(vm_id, net_id)
441
        self.assertEqual(self.client.http_client.url, self.url)
442
        self.assertEqual(
443
            self.client.http_client.path,
444
            '/networks/%s/action' % net_id)
445
        self.assertEqual(
446
            PR.call_args[0],
447
            ('post', '{"add": {"serverRef": %s}}' % vm_id, {}, {}))
448

449
    @patch('%s.networks_post' % cyclades_pkg, return_value=FR())
450
    def test_disconnect_server(self, NP):
451
        vm_id = vm_recv['server']['id']
452
        net_id = net_recv['network']['id']
453
        nic_id = 'nic-%s-%s' % (net_id, vm_id)
454
        vm_nics = [
455
            dict(id=nic_id, network_id=net_id),
456
            dict(id='another-nic-id', network_id='another-net-id'),
457
            dict(id=nic_id * 2, network_id=net_id * 2)]
458
        with patch.object(
459
                CycladesClient,
460
                'list_server_nics',
461
                return_value=vm_nics) as LSN:
462
            r = self.client.disconnect_server(vm_id, nic_id)
463
            self.assertEqual(r, 1)
464
            self.assertEqual(LSN.call_args[0], (vm_id,))
465
            self.assertEqual(NP.call_args[0], (net_id, 'action'))
466
            self.assertEqual(
467
                NP.call_args[1],
468
                dict(json_data=dict(remove=dict(attachment=nic_id))))
469

470
    @patch('%s.perform_request' % khttp, return_value=FR())
471
    def test_list_server_nics(self, PR):
472
        vm_id = vm_recv['server']['id']
473
        nics = dict(addresses=dict(values=[dict(id='nic1'), dict(id='nic2')]))
474
        FR.json = nics
475
        r = self.client.list_server_nics(vm_id)
476
        self.assertEqual(self.client.http_client.url, self.url)
477
        self.assertEqual(
478
            self.client.http_client.path,
479
            '/servers/%s/ips' % vm_id)
480
        expected = nics['addresses']['values']
481
        for i in range(len(r)):
482
            self.assert_dicts_are_equal(r[i], expected[i])
483

484
    @patch('%s.perform_request' % khttp, return_value=FR())
485
    def test_list_networks(self, PR):
486
        FR.json = net_list
487
        r = self.client.list_networks()
488
        self.assertEqual(self.client.http_client.url, self.url)
489
        self.assertEqual(self.client.http_client.path, '/networks')
490
        expected = net_list['networks']['values']
491
        for i in range(len(r)):
492
            self.assert_dicts_are_equal(expected[i], r[i])
493
        self.client.list_networks(detail=True)
494
        self.assertEqual(self.client.http_client.url, self.url)
495
        self.assertEqual(self.client.http_client.path, '/networks/detail')
496

497
    @patch('%s.perform_request' % khttp, return_value=FR())
498
    def test_list_network_nics(self, PR):
499
        net_id = net_recv['network']['id']
500
        FR.json = net_recv
501
        r = self.client.list_network_nics(net_id)
502
        self.assertEqual(self.client.http_client.url, self.url)
503
        self.assertEqual(
504
            self.client.http_client.path,
505
            '/networks/%s' % net_id)
506
        expected = net_recv['network']['attachments']['values']
507
        for i in range(len(r)):
508
            self.assert_dicts_are_equal(r[i], expected[i])
509

510
    @patch('%s.networks_post' % cyclades_pkg, return_value=FR())
511
    def test_disconnect_network_nics(self, NP):
512
        net_id = net_recv['network']['id']
513
        nics = ['nic1', 'nic2', 'nic3']
514
        with patch.object(
515
                CycladesClient,
516
                'list_network_nics',
517
                return_value=nics) as lnn:
518
            self.client.disconnect_network_nics(net_id)
519
            lnn.assert_called_once_with(net_id)
520
            for i in range(len(nics)):
521
                expected = call(net_id, 'action', json_data=dict(
522
                    remove=dict(attachment=nics[i])))
523
                self.assertEqual(expected, NP.mock_calls[i])
524

525
    @patch('%s.perform_request' % khttp, return_value=FR())
526
    def test_get_network_details(self, PR):
527
        FR.json = net_recv
528
        net_id = net_recv['network']['id']
529
        r = self.client.get_network_details(net_id)
530
        self.assertEqual(self.client.http_client.url, self.url)
531
        self.assertEqual(
532
            self.client.http_client.path,
533
            '/networks/%s' % net_id)
534
        self.assert_dicts_are_equal(r, net_recv['network'])
535

536
    @patch('%s.perform_request' % khttp, return_value=FR())
537
    def test_update_network_name(self, PR):
538
        net_id = net_recv['network']['id']
539
        new_name = '%s_new' % net_id
540
        FR.status_code = 204
541
        self.client.update_network_name(net_id, new_name)
542
        self.assertEqual(self.client.http_client.url, self.url)
543
        self.assertEqual(self.client.http_client.path, '/networks/%s' % net_id)
544
        (method, data, a_headers, a_params) = PR.call_args[0]
545
        self.assert_dicts_are_equal(
546
            dict(network=dict(name=new_name)),
547
            loads(data))
548

549
    @patch('%s.perform_request' % khttp, return_value=FR())
550
    def test_delete_server(self, PR):
551
        vm_id = vm_recv['server']['id']
552
        FR.status_code = 204
553
        self.client.delete_server(vm_id)
554
        self.assertEqual(self.client.http_client.url, self.url)
555
        self.assertEqual(self.client.http_client.path, '/servers/%s' % vm_id)
556

557
    @patch('%s.perform_request' % khttp, return_value=FR())
558
    def test_delete_image(self, PR):
559
        FR.status_code = 204
560
        self.client.delete_image(img_ref)
561
        self.assertEqual(self.client.http_client.url, self.url)
562
        self.assertEqual(self.client.http_client.path, '/images/%s' % img_ref)
563

564
    @patch('%s.perform_request' % khttp, return_value=FR())
565
    def test_delete_network(self, PR):
566
        net_id = net_recv['network']['id']
567
        FR.status_code = 204
568
        self.client.delete_network(net_id)
569
        self.assertEqual(self.client.http_client.url, self.url)
570
        self.assertEqual(self.client.http_client.path, '/networks/%s' % net_id)
571

572
    @patch('%s.perform_request' % khttp, return_value=FR())
573
    def test_create_image_metadata(self, PR):
574
        metadata = dict(m1='v1', m2='v2', m3='v3')
575
        FR.json = dict(meta=img_recv['image'])
576
        self.assertRaises(
577
            ClientError,
578
            self.client.create_image_metadata,
579
            img_ref, 'key', 'value')
580
        FR.status_code = 201
581
        for k, v in metadata.items():
582
            r = self.client.create_image_metadata(img_ref, k, v)
583
            self.assertEqual(self.client.http_client.url, self.url)
584
            self.assertEqual(
585
                self.client.http_client.path,
586
                '/images/%s/meta/%s' % (img_ref, k))
587
            (method, data, a_headers, a_params) = PR.call_args[0]
588
            self.assertEqual(dict(meta={k: v}), loads(data))
589
            self.assert_dicts_are_equal(r, img_recv['image'])
590

591
    @patch('%s.images_post' % cyclades_pkg, return_value=FR())
592
    def test_update_image_metadata(self, images_post):
593
        metadata = dict(m1='v1', m2='v2', m3='v3')
594
        FR.json = dict(metadata=metadata)
595
        r = self.client.update_image_metadata(img_ref, **metadata)
596
        self.assert_dicts_are_equal(r, metadata)
597
        (called_id, cmd) = images_post.call_args[0]
598
        self.assertEqual(called_id, img_ref)
599
        self.assertEqual(cmd, 'meta')
600
        data = images_post.call_args[1]['json_data']
601
        self.assert_dicts_are_equal(data, dict(metadata=metadata))
602

603
    @patch('%s.images_delete' % cyclades_pkg, return_value=FR())
604
    def test_delete_image_metadata(self, images_delete):
605
        key = 'metakey'
606
        self.client.delete_image_metadata(img_ref, key)
607
        self.assertEqual(
608
            (img_ref, '/meta/' + key),
609
            images_delete.call_args[0])
610
    """
611

    
612
if __name__ == '__main__':
613
    from sys import argv
614
    from kamaki.clients.test import runTestCase
615
    runTestCase(Cyclades, 'Cyclades (multi) Client', argv[1:])