Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (24.7 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
compute_pkg_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
    @patch('%s.servers_get' % compute_pkg, return_value=FR())
232
    def test_get_server_metadata(self, SG):
233
        vm_id = vm_recv['server']['id']
234
        metadata = dict(m1='v1', m2='v2', m3='v3')
235
        FR.json = dict(metadata=dict(values=metadata))
236
        r = self.client.get_server_metadata(vm_id)
237
        self.assertEqual(SG.mock_calls[-1], call(vm_id, '/meta'))
238
        self.assert_dicts_are_equal(r, metadata)
239

    
240
        for k, v in metadata.items():
241
            FR.json = dict(meta={k: v})
242
            r = self.client.get_server_metadata(vm_id, k)
243
            self.assert_dicts_are_equal(r, {k: v})
244
            self.assertEqual(SG.mock_calls[-1], call(vm_id, '/meta/%s' % k))
245

    
246
    @patch('%s.servers_post' % compute_pkg, return_value=FR())
247
    def test_update_server_metadata(self, SP):
248
        vm_id = vm_recv['server']['id']
249
        metadata = dict(m1='v1', m2='v2', m3='v3')
250
        FR.json = dict(metadata=metadata)
251
        r = self.client.update_server_metadata(vm_id, **metadata)
252
        self.assert_dicts_are_equal(r, metadata)
253
        self.assertEqual(SP.mock_calls[-1], call(
254
            vm_id, 'meta',
255
            json_data=dict(metadata=metadata), success=201))
256

    
257
    """
258
    @patch('%s.servers_delete' % compute_pkg, return_value=FR())
259
    def test_delete_server_metadata(self, servers_delete):
260
        vm_id = vm_recv['server']['id']
261
        key = 'metakey'
262
        self.client.delete_server_metadata(vm_id, key)
263
        self.assertEqual((vm_id, 'meta/' + key), servers_delete.call_args[0])
264

265
    @patch('%s.perform_request' % compute_pkg, return_value=FR())
266
    def test_list_flavors(self, PR):
267
        FR.json = flavor_list
268
        r = self.client.list_flavors()
269
        self.assertEqual(self.client.http_client.url, self.url)
270
        self.assertEqual(self.client.http_client.path, '/flavors')
271
        (method, data, a_headers, a_params) = PR.call_args[0]
272
        self.assert_dicts_are_equal(dict(values=r), flavor_list['flavors'])
273
        r = self.client.list_flavors(detail=True)
274
        self.assertEqual(self.client.http_client.url, self.url)
275
        self.assertEqual(self.client.http_client.path, '/flavors/detail')
276

277
    @patch('%s.perform_request' % compute_pkg, return_value=FR())
278
    def test_get_flavor_details(self, PR):
279
        FR.json = dict(flavor=flavor_list['flavors'])
280
        r = self.client.get_flavor_details(fid)
281
        self.assertEqual(self.client.http_client.url, self.url)
282
        self.assertEqual(self.client.http_client.path, '/flavors/%s' % fid)
283
        self.assert_dicts_are_equal(r, flavor_list['flavors'])
284

285
    @patch('%s.perform_request' % compute_pkg, return_value=FR())
286
    def test_list_images(self, PR):
287
        FR.json = img_list
288
        r = self.client.list_images()
289
        self.assertEqual(self.client.http_client.url, self.url)
290
        self.assertEqual(self.client.http_client.path, '/images')
291
        expected = img_list['images']['values']
292
        for i in range(len(r)):
293
            self.assert_dicts_are_equal(expected[i], r[i])
294
        self.client.list_images(detail=True)
295
        self.assertEqual(self.client.http_client.url, self.url)
296
        self.assertEqual(self.client.http_client.path, '/images/detail')
297

298
    @patch('%s.perform_request' % compute_pkg, return_value=FR())
299
    def test_get_image_details(self, PR):
300
        FR.json = img_recv
301
        r = self.client.get_image_details(img_ref)
302
        self.assertEqual(self.client.http_client.url, self.url)
303
        self.assertEqual(self.client.http_client.path, '/images/%s' % img_ref)
304
        self.assert_dicts_are_equal(r, img_recv['image'])
305

306
    @patch('%s.images_get' % compute_pkg, return_value=FR())
307
    def test_get_image_metadata(self, IG):
308
        FR.json = dict(metadata=dict(values=img_recv['image']))
309
        r = self.client.get_image_metadata(img_ref)
310
        self.assertEqual(IG.call_args[0], ('%s' % img_ref, '/meta'))
311
        self.assert_dicts_are_equal(img_recv['image'], r)
312
        FR.json = dict(meta=img_recv['image'])
313
        key = 'somekey'
314
        self.client.get_image_metadata(img_ref, key)
315
        self.assertEqual(IG.call_args[0], ('%s' % img_ref, '/meta/%s' % key))
316

317
    @patch('%s.perform_request' % compute_pkg, return_value=FR())
318
    def test_shutdown_server(self, PR):
319
        vm_id = vm_recv['server']['id']
320
        FR.status_code = 202
321
        self.client.shutdown_server(vm_id)
322
        self.assertEqual(self.client.http_client.url, self.url)
323
        self.assertEqual(
324
            self.client.http_client.path,
325
            '/servers/%s/action' % vm_id)
326
        self.assertEqual(
327
            PR.call_args[0],
328
            ('post',  '{"shutdown": {}}', {}, {}))
329

330
    @patch('%s.perform_request' % compute_pkg, return_value=FR())
331
    def test_start_server(self, PR):
332
        vm_id = vm_recv['server']['id']
333
        FR.status_code = 202
334
        self.client.start_server(vm_id)
335
        self.assertEqual(self.client.http_client.url, self.url)
336
        self.assertEqual(
337
            self.client.http_client.path,
338
            '/servers/%s/action' % vm_id)
339
        self.assertEqual(PR.call_args[0], ('post',  '{"start": {}}', {}, {}))
340

341
    @patch('%s.perform_request' % compute_pkg, return_value=FR())
342
    def test_get_server_console(self, PR):
343
        cnsl = dict(console=dict(info1='i1', info2='i2', info3='i3'))
344
        FR.json = cnsl
345
        vm_id = vm_recv['server']['id']
346
        r = self.client.get_server_console(vm_id)
347
        self.assertEqual(self.client.http_client.url, self.url)
348
        self.assertEqual(
349
            self.client.http_client.path,
350
            '/servers/%s/action' % vm_id)
351
        self.assert_dicts_are_equal(cnsl['console'], r)
352
        self.assertEqual(
353
            PR.call_args[0],
354
            ('post',  '{"console": {"type": "vnc"}}', {}, {}))
355

356
    def test_get_firewall_profile(self):
357
        vm_id = vm_recv['server']['id']
358
        v = 'Some profile'
359
        ret = {'attachments': {'values': [{'firewallProfile': v, 1:1}]}}
360
        with patch.object(
361
                CycladesClient,
362
                'get_server_details',
363
                return_value=ret) as GSD:
364
            r = self.client.get_firewall_profile(vm_id)
365
            self.assertEqual(r, v)
366
            self.assertEqual(GSD.call_args[0], (vm_id,))
367
            ret['attachments']['values'][0].pop('firewallProfile')
368
            self.assertRaises(
369
                ClientError,
370
                self.client.get_firewall_profile,
371
                vm_id)
372

373
    @patch('%s.perform_request' % compute_pkg, return_value=FR())
374
    def test_set_firewall_profile(self, PR):
375
        vm_id = vm_recv['server']['id']
376
        v = 'Some profile'
377
        FR.status_code = 202
378
        self.client.set_firewall_profile(vm_id, v)
379
        self.assertEqual(self.client.http_client.url, self.url)
380
        self.assertEqual(
381
            self.client.http_client.path,
382
            '/servers/%s/action' % vm_id)
383
        self.assertEqual(PR.call_args[0], (
384
            'post',
385
            '{"firewallProfile": {"profile": "%s"}}' % v,
386
            {},
387
            {}))
388

389
    @patch('%s.perform_request' % compute_pkg, return_value=FR())
390
    def test_get_server_stats(self, PR):
391
        vm_id = vm_recv['server']['id']
392
        stats = dict(stat1='v1', stat2='v2', stat3='v3', stat4='v4')
393
        FR.json = dict(stats=stats)
394
        r = self.client.get_server_stats(vm_id)
395
        self.assertEqual(self.client.http_client.url, self.url)
396
        self.assertEqual(
397
            self.client.http_client.path,
398
            '/servers/%s/stats' % vm_id)
399
        self.assert_dicts_are_equal(stats, r)
400

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

427
    @patch('%s.perform_request' % compute_pkg, return_value=FR())
428
    def test_connect_server(self, PR):
429
        vm_id = vm_recv['server']['id']
430
        net_id = net_recv['network']['id']
431
        FR.status_code = 202
432
        self.client.connect_server(vm_id, net_id)
433
        self.assertEqual(self.client.http_client.url, self.url)
434
        self.assertEqual(
435
            self.client.http_client.path,
436
            '/networks/%s/action' % net_id)
437
        self.assertEqual(
438
            PR.call_args[0],
439
            ('post', '{"add": {"serverRef": %s}}' % vm_id, {}, {}))
440

441
    @patch('%s.networks_post' % compute_pkg, return_value=FR())
442
    def test_disconnect_server(self, NP):
443
        vm_id = vm_recv['server']['id']
444
        net_id = net_recv['network']['id']
445
        nic_id = 'nic-%s-%s' % (net_id, vm_id)
446
        vm_nics = [
447
            dict(id=nic_id, network_id=net_id),
448
            dict(id='another-nic-id', network_id='another-net-id'),
449
            dict(id=nic_id * 2, network_id=net_id * 2)]
450
        with patch.object(
451
                CycladesClient,
452
                'list_server_nics',
453
                return_value=vm_nics) as LSN:
454
            r = self.client.disconnect_server(vm_id, nic_id)
455
            self.assertEqual(r, 1)
456
            self.assertEqual(LSN.call_args[0], (vm_id,))
457
            self.assertEqual(NP.call_args[0], (net_id, 'action'))
458
            self.assertEqual(
459
                NP.call_args[1],
460
                dict(json_data=dict(remove=dict(attachment=nic_id))))
461

462
    @patch('%s.perform_request' % compute_pkg, return_value=FR())
463
    def test_list_server_nics(self, PR):
464
        vm_id = vm_recv['server']['id']
465
        nics = dict(addresses=dict(values=[dict(id='nic1'), dict(id='nic2')]))
466
        FR.json = nics
467
        r = self.client.list_server_nics(vm_id)
468
        self.assertEqual(self.client.http_client.url, self.url)
469
        self.assertEqual(
470
            self.client.http_client.path,
471
            '/servers/%s/ips' % vm_id)
472
        expected = nics['addresses']['values']
473
        for i in range(len(r)):
474
            self.assert_dicts_are_equal(r[i], expected[i])
475

476
    @patch('%s.perform_request' % compute_pkg, return_value=FR())
477
    def test_list_networks(self, PR):
478
        FR.json = net_list
479
        r = self.client.list_networks()
480
        self.assertEqual(self.client.http_client.url, self.url)
481
        self.assertEqual(self.client.http_client.path, '/networks')
482
        expected = net_list['networks']['values']
483
        for i in range(len(r)):
484
            self.assert_dicts_are_equal(expected[i], r[i])
485
        self.client.list_networks(detail=True)
486
        self.assertEqual(self.client.http_client.url, self.url)
487
        self.assertEqual(self.client.http_client.path, '/networks/detail')
488

489
    @patch('%s.perform_request' % compute_pkg, return_value=FR())
490
    def test_list_network_nics(self, PR):
491
        net_id = net_recv['network']['id']
492
        FR.json = net_recv
493
        r = self.client.list_network_nics(net_id)
494
        self.assertEqual(self.client.http_client.url, self.url)
495
        self.assertEqual(
496
            self.client.http_client.path,
497
            '/networks/%s' % net_id)
498
        expected = net_recv['network']['attachments']['values']
499
        for i in range(len(r)):
500
            self.assert_dicts_are_equal(r[i], expected[i])
501

502
    @patch('%s.networks_post' % compute_pkg, return_value=FR())
503
    def test_disconnect_network_nics(self, NP):
504
        net_id = net_recv['network']['id']
505
        nics = ['nic1', 'nic2', 'nic3']
506
        with patch.object(
507
                CycladesClient,
508
                'list_network_nics',
509
                return_value=nics) as lnn:
510
            self.client.disconnect_network_nics(net_id)
511
            lnn.assert_called_once_with(net_id)
512
            for i in range(len(nics)):
513
                expected = call(net_id, 'action', json_data=dict(
514
                    remove=dict(attachment=nics[i])))
515
                self.assertEqual(expected, NP.mock_calls[i])
516

517
    @patch('%s.perform_request' % compute_pkg, return_value=FR())
518
    def test_get_network_details(self, PR):
519
        FR.json = net_recv
520
        net_id = net_recv['network']['id']
521
        r = self.client.get_network_details(net_id)
522
        self.assertEqual(self.client.http_client.url, self.url)
523
        self.assertEqual(
524
            self.client.http_client.path,
525
            '/networks/%s' % net_id)
526
        self.assert_dicts_are_equal(r, net_recv['network'])
527

528
    @patch('%s.perform_request' % compute_pkg, return_value=FR())
529
    def test_update_network_name(self, PR):
530
        net_id = net_recv['network']['id']
531
        new_name = '%s_new' % net_id
532
        FR.status_code = 204
533
        self.client.update_network_name(net_id, new_name)
534
        self.assertEqual(self.client.http_client.url, self.url)
535
        self.assertEqual(self.client.http_client.path, '/networks/%s' % net_id)
536
        (method, data, a_headers, a_params) = PR.call_args[0]
537
        self.assert_dicts_are_equal(
538
            dict(network=dict(name=new_name)),
539
            loads(data))
540

541
    @patch('%s.perform_request' % compute_pkg, return_value=FR())
542
    def test_delete_server(self, PR):
543
        vm_id = vm_recv['server']['id']
544
        FR.status_code = 204
545
        self.client.delete_server(vm_id)
546
        self.assertEqual(self.client.http_client.url, self.url)
547
        self.assertEqual(self.client.http_client.path, '/servers/%s' % vm_id)
548

549
    @patch('%s.perform_request' % compute_pkg, return_value=FR())
550
    def test_delete_image(self, PR):
551
        FR.status_code = 204
552
        self.client.delete_image(img_ref)
553
        self.assertEqual(self.client.http_client.url, self.url)
554
        self.assertEqual(self.client.http_client.path, '/images/%s' % img_ref)
555

556
    @patch('%s.perform_request' % compute_pkg, return_value=FR())
557
    def test_delete_network(self, PR):
558
        net_id = net_recv['network']['id']
559
        FR.status_code = 204
560
        self.client.delete_network(net_id)
561
        self.assertEqual(self.client.http_client.url, self.url)
562
        self.assertEqual(self.client.http_client.path, '/networks/%s' % net_id)
563

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

583
    @patch('%s.images_post' % compute_pkg, return_value=FR())
584
    def test_update_image_metadata(self, images_post):
585
        metadata = dict(m1='v1', m2='v2', m3='v3')
586
        FR.json = dict(metadata=metadata)
587
        r = self.client.update_image_metadata(img_ref, **metadata)
588
        self.assert_dicts_are_equal(r, metadata)
589
        (called_id, cmd) = images_post.call_args[0]
590
        self.assertEqual(called_id, img_ref)
591
        self.assertEqual(cmd, 'meta')
592
        data = images_post.call_args[1]['json_data']
593
        self.assert_dicts_are_equal(data, dict(metadata=metadata))
594

595
    @patch('%s.images_delete' % compute_pkg, return_value=FR())
596
    def test_delete_image_metadata(self, images_delete):
597
        key = 'metakey'
598
        self.client.delete_image_metadata(img_ref, key)
599
        self.assertEqual(
600
            (img_ref, '/meta/' + key),
601
            images_delete.call_args[0])
602
    """
603

    
604
if __name__ == '__main__':
605
    from sys import argv
606
    from kamaki.clients.test import runTestCase
607
    runTestCase(Cyclades, 'Cyclades (multi) Client', argv[1:])