Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / test / cyclades.py @ 386d82a1

History | View | Annotate | Download (22.8 kB)

1
# Copyright 2012-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
from mock import patch, Mock
34
from unittest import TestCase
35
from json import loads
36

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

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

    
96

    
97
class Cyclades(TestCase):
98

    
99
    def assert_dicts_are_equal(self, d1, d2):
100
        for k, v in d1.items():
101
            self.assertTrue(k in d2)
102
            if isinstance(v, dict):
103
                self.assert_dicts_are_equal(v, d2[k])
104
            else:
105
                self.assertEqual(unicode(v), unicode(d2[k]))
106

    
107
    class FR(object):
108
        """FR stands for Fake Response"""
109
        json = vm_recv
110
        headers = {}
111
        content = json
112
        status = None
113
        status_code = 200
114

    
115
        def release(self):
116
            pass
117

    
118
    """Set up a Cyclades thorough test"""
119
    def setUp(self):
120
        self.url = 'http://cyclades.example.com'
121
        self.token = 'cyc14d3s70k3n'
122
        self.client = CycladesClient(self.url, self.token)
123
        from kamaki.clients.connection.kamakicon import KamakiHTTPConnection
124
        self.C = KamakiHTTPConnection
125

    
126
    def tearDown(self):
127
        self.FR.status_code = 200
128
        self.FR.json = vm_recv
129

    
130
    def test_create_server(self):
131
        self.client.get_image_details = Mock(return_value=img_recv['image'])
132
        with patch.object(Client, 'request', side_effect=ClientError(
133
                'REQUEST ENTITY TOO LARGE',
134
                status=403)):
135
            self.assertRaises(
136
                ClientError,
137
                self.client.create_server,
138
                vm_name, fid, img_ref)
139

    
140
        with patch.object(
141
                self.C,
142
                'perform_request',
143
                return_value=self.FR()) as perform_req:
144
            self.assertRaises(
145
                ClientError,
146
                self.client.create_server,
147
                vm_name, fid, img_ref)
148
            self.FR.status_code = 202
149
            r = self.client.create_server(vm_name, fid, img_ref)
150
            self.assertEqual(self.client.http_client.url, self.url)
151
            self.assertEqual(self.client.http_client.path, '/servers')
152
            (method, data, a_headers, a_params) = perform_req.call_args[0]
153
            self.assert_dicts_are_equal(loads(data), vm_send)
154
            self.assert_dicts_are_equal(r, vm_recv['server'])
155
            prsn = 'Personality string (does not work with real servers)'
156
            self.client.create_server(vm_name, fid, img_ref, prsn)
157
            (method, data, a_headers, a_params) = perform_req.call_args[0]
158
            data = loads(data)
159
            self.assertTrue('personality' in data['server'])
160
            self.assertEqual(prsn, data['server']['personality'])
161

    
162
    def test_list_servers(self):
163
        self.FR.json = vm_list
164
        with patch.object(
165
                self.C,
166
                'perform_request',
167
                return_value=self.FR()) as perform_req:
168
            r = self.client.list_servers()
169
            self.assertEqual(self.client.http_client.url, self.url)
170
            self.assertEqual(self.client.http_client.path, '/servers')
171
            (method, data, a_headers, a_params) = perform_req.call_args[0]
172
            self.assert_dicts_are_equal(dict(values=r), vm_list['servers'])
173
            r = self.client.list_servers(detail=True)
174
            self.assertEqual(self.client.http_client.url, self.url)
175
            self.assertEqual(self.client.http_client.path, '/servers/detail')
176
        with patch.object(
177
                CycladesClientApi,
178
                'servers_get',
179
                return_value=self.FR()) as servers_get:
180
            self.client.list_servers(changes_since=True)
181
            self.assertTrue(servers_get.call_args[1]['changes_since'])
182

    
183
    def test_get_server_details(self):
184
        vm_id = vm_recv['server']['id']
185
        with patch.object(self.C, 'perform_request', return_value=self.FR()):
186
            r = self.client.get_server_details(vm_id)
187
            self.assertEqual(self.client.http_client.url, self.url)
188
            self.assertEqual(
189
                self.client.http_client.path,
190
                '/servers/%s' % vm_id)
191
            self.assert_dicts_are_equal(r, vm_recv['server'])
192

    
193
    def test_update_server_name(self):
194
        vm_id = vm_recv['server']['id']
195
        new_name = vm_name + '_new'
196
        self.FR.status_code = 204
197
        with patch.object(
198
                self.C,
199
                'perform_request',
200
                return_value=self.FR()) as perform_req:
201
            self.client.update_server_name(vm_id, new_name)
202
            self.assertEqual(self.client.http_client.url, self.url)
203
            self.assertEqual(
204
                self.client.http_client.path,
205
                '/servers/%s' % vm_id)
206
            (method, data, a_headers, a_params) = perform_req.call_args[0]
207
            self.assert_dicts_are_equal(
208
                dict(server=dict(name=new_name)),
209
                loads(data))
210

    
211
    def test_reboot_server(self):
212
        vm_id = vm_recv['server']['id']
213
        self.FR.status_code = 202
214
        with patch.object(
215
                self.C,
216
                'perform_request',
217
                return_value=self.FR()) as perform_req:
218
            self.client.reboot_server(vm_id)
219
            self.assertEqual(self.client.http_client.url, self.url)
220
            self.assertEqual(
221
                self.client.http_client.path,
222
                '/servers/%s/action' % vm_id)
223
            (method, data, a_headers, a_params) = perform_req.call_args[0]
224
            self.assert_dicts_are_equal(
225
                dict(reboot=dict(type='SOFT')),
226
                loads(data))
227

    
228
    def test_create_server_metadata(self):
229
        vm_id = vm_recv['server']['id']
230
        metadata = dict(m1='v1', m2='v2', m3='v3')
231
        self.FR.json = dict(meta=vm_recv['server'])
232
        with patch.object(
233
                self.C,
234
                'perform_request',
235
                return_value=self.FR()) as perform_req:
236
            self.assertRaises(
237
                ClientError,
238
                self.client.create_server_metadata,
239
                vm_id, 'key', 'value')
240
            self.FR.status_code = 201
241
            for k, v in metadata.items():
242
                r = self.client.create_server_metadata(vm_id, k, v)
243
                self.assertEqual(self.client.http_client.url, self.url)
244
                self.assertEqual(
245
                    self.client.http_client.path,
246
                    '/servers/%s/meta/%s' % (vm_id, k))
247
                (method, data, a_headers, a_params) = perform_req.call_args[0]
248
                self.assertEqual(dict(meta={k: v}), loads(data))
249
                self.assert_dicts_are_equal(r, vm_recv['server'])
250

    
251
    def test_get_server_metadata(self):
252
        vm_id = vm_recv['server']['id']
253
        metadata = dict(m1='v1', m2='v2', m3='v3')
254
        with patch.object(self.C, 'perform_request', return_value=self.FR()):
255
            self.FR.json = dict(metadata=dict(values=metadata))
256
            r = self.client.get_server_metadata(vm_id)
257
            self.assertEqual(self.client.http_client.url, self.url)
258
            self.assertEqual(
259
                self.client.http_client.path,
260
                '/servers/%s/meta' % vm_id)
261
            self.assert_dicts_are_equal(r, metadata)
262

    
263
            for k, v in metadata.items():
264
                self.FR.json = dict(meta={k: v})
265
                r = self.client.get_server_metadata(vm_id, k)
266
                self.assertEqual(self.client.http_client.url, self.url)
267
                self.assertEqual(
268
                    self.client.http_client.path,
269
                    '/servers/%s/meta/%s' % (vm_id, k))
270
                self.assert_dicts_are_equal(r, {k: v})
271

    
272
    def test_update_server_metadata(self):
273
        vm_id = vm_recv['server']['id']
274
        metadata = dict(m1='v1', m2='v2', m3='v3')
275
        self.FR.json = dict(metadata=metadata)
276
        with patch.object(
277
                CycladesClientApi,
278
                'servers_post',
279
                return_value=self.FR()) as servers_post:
280
            r = self.client.update_server_metadata(vm_id, **metadata)
281
            self.assert_dicts_are_equal(r, metadata)
282
            (called_id, cmd) = servers_post.call_args[0]
283
            self.assertEqual(called_id, vm_id)
284
            self.assertEqual(cmd, 'meta')
285
            data = servers_post.call_args[1]['json_data']
286
            self.assert_dicts_are_equal(data, dict(metadata=metadata))
287

    
288
    def test_delete_server_metadata(self):
289
        vm_id = vm_recv['server']['id']
290
        key = 'metakey'
291
        with patch.object(
292
                CycladesClientApi,
293
                'servers_delete',
294
                return_value=self.FR()) as servers_delete:
295
            self.client.delete_server_metadata(vm_id, key)
296
            self.assertEqual(
297
                (vm_id, 'meta/' + key),
298
                servers_delete.call_args[0])
299

    
300
    def test_list_flavors(self):
301
        self.FR.json = flavor_list
302
        with patch.object(
303
                self.C,
304
                'perform_request',
305
                return_value=self.FR()) as perform_req:
306
            r = self.client.list_flavors()
307
            self.assertEqual(self.client.http_client.url, self.url)
308
            self.assertEqual(self.client.http_client.path, '/flavors')
309
            (method, data, a_headers, a_params) = perform_req.call_args[0]
310
            self.assert_dicts_are_equal(dict(values=r), flavor_list['flavors'])
311
            r = self.client.list_flavors(detail=True)
312
            self.assertEqual(self.client.http_client.url, self.url)
313
            self.assertEqual(self.client.http_client.path, '/flavors/detail')
314

    
315
    def test_get_flavor_details(self):
316
        self.FR.json = dict(flavor=flavor_list['flavors'])
317
        with patch.object(self.C, 'perform_request', return_value=self.FR()):
318
            r = self.client.get_flavor_details(fid)
319
            self.assertEqual(self.client.http_client.url, self.url)
320
            self.assertEqual(
321
                self.client.http_client.path,
322
                '/flavors/%s' % fid)
323
            self.assert_dicts_are_equal(r, flavor_list['flavors'])
324

    
325
    def test_list_images(self):
326
        self.FR.json = img_list
327
        with patch.object(self.C, 'perform_request', return_value=self.FR()):
328
            r = self.client.list_images()
329
            self.assertEqual(self.client.http_client.url, self.url)
330
            self.assertEqual(self.client.http_client.path, '/images')
331
            expected = img_list['images']['values']
332
            for i in range(len(r)):
333
                self.assert_dicts_are_equal(expected[i], r[i])
334
            self.client.list_images(detail=True)
335
            self.assertEqual(self.client.http_client.url, self.url)
336
            self.assertEqual(self.client.http_client.path, '/images/detail')
337

    
338
    def test_get_image_details(self):
339
        self.FR.json = img_recv
340
        with patch.object(self.C, 'perform_request', return_value=self.FR()):
341
            r = self.client.get_image_details(img_ref)
342
            self.assertEqual(self.client.http_client.url, self.url)
343
            self.assertEqual(
344
                self.client.http_client.path,
345
                '/images/%s' % img_ref)
346
            self.assert_dicts_are_equal(r, img_recv['image'])
347

    
348
    def test_get_image_metadata(self):
349
        self.FR.json = dict(metadata=dict(values=img_recv['image']))
350
        with patch.object(
351
                CycladesClient,
352
                'images_get',
353
                return_value=self.FR()) as inner:
354
            r = self.client.get_image_metadata(img_ref)
355
            self.assertEqual(inner.call_args[0], ('%s' % img_ref, '/meta'))
356
            self.assert_dicts_are_equal(img_recv['image'], r)
357
            self.FR.json = dict(meta=img_recv['image'])
358
            key = 'somekey'
359
            self.client.get_image_metadata(img_ref, key)
360
            self.assertEqual(
361
                inner.call_args[0],
362
                ('%s' % img_ref, '/meta/%s' % key))
363

    
364
    def test_shutdown_server(self):
365
        vm_id = vm_recv['server']['id']
366
        self.FR.status_code = 202
367
        with patch.object(
368
                self.C,
369
                'perform_request',
370
                return_value=self.FR()) as perform_req:
371
            self.client.shutdown_server(vm_id)
372
            self.assertEqual(self.client.http_client.url, self.url)
373
            self.assertEqual(
374
                self.client.http_client.path,
375
                '/servers/%s/action' % vm_id)
376
            self.assertEqual(
377
                perform_req.call_args[0],
378
                ('post',  '{"shutdown": {}}', {}, {}))
379

    
380
    """
381
    def test_start_server(self):
382
        self.client.start_server(self.server1['id'])
383
        self._wait_for_status(self.server1['id'], 'STOPPED')
384
        r = self.client.get_server_details(self.server1['id'])
385
        self.assertEqual(r['status'], 'ACTIVE')
386

387
    def test_get_server_console(self):
388
        r = self.client.get_server_console(self.server2['id'])
389
        self.assertTrue('host' in r)
390
        self.assertTrue('password' in r)
391
        self.assertTrue('port' in r)
392
        self.assertTrue('type' in r)
393

394
    def test_get_firewall_profile(self):
395
        self._wait_for_status(self.server1['id'], 'BUILD')
396
        fprofile = self.client.get_firewall_profile(self.server1['id'])
397
        self.assertTrue(fprofile in self.PROFILES)
398

399
    def test_set_firewall_profile(self):
400
        self._wait_for_status(self.server1['id'], 'BUILD')
401
        PROFILES = ['DISABLED', 'ENABLED', 'DISABLED', 'PROTECTED']
402
        fprofile = self.client.get_firewall_profile(self.server1['id'])
403
        print('')
404
        count_success = 0
405
        for counter, fprofile in enumerate(PROFILES):
406
            npos = counter + 1
407
            try:
408
                nprofile = PROFILES[npos]
409
            except IndexError:
410
                nprofile = PROFILES[0]
411
            print('\tprofile swap %s: %s -> %s' % (npos, fprofile, nprofile))
412
            self.client.set_firewall_profile(self.server1['id'], nprofile)
413
            time.sleep(0.5)
414
            self.client.reboot_server(self.server1['id'], hard=True)
415
            time.sleep(1)
416
            self._wait_for_status(self.server1['id'], 'REBOOT')
417
            time.sleep(0.5)
418
            changed = self.client.get_firewall_profile(self.server1['id'])
419
            try:
420
                self.assertEqual(changed, nprofile)
421
            except AssertionError as err:
422
                if count_success:
423
                    print('\tFAIL in swap #%s' % npos)
424
                    break
425
                else:
426
                    raise err
427
            count_success += 1
428

429
    def test_get_server_stats(self):
430
        r = self.client.get_server_stats(self.server1['id'])
431
        it = ('cpuBar', 'cpuTimeSeries', 'netBar', 'netTimeSeries', 'refresh')
432
        for term in it:
433
            self.assertTrue(term in r)
434

435
    def test_create_network(self):
436
        print('\twith no params')
437
        self.network1 = self._create_network(self.netname1)
438
        self._wait_for_network(self.network1['id'], 'ACTIVE')
439
        n1id = self.network1['id']
440
        self.network1 = self.client.get_network_details(n1id)
441
        nets = self.client.list_networks(self.network1['id'])
442
        chosen = [net for net in nets if net['id'] == n1id][0]
443
        chosen.pop('updated')
444
        net1 = dict(self.network1)
445
        net1.pop('updated')
446
        self.assert_dicts_are_equal(chosen, net1)
447
        for param, val in dict(
448
                cidr='192.168.0.0/24',
449
                gateway='192.168.0.1',
450
                type='MAC_FILTERED',
451
                dhcp=True).items():
452
            print('\tdelete %s to avoid max net limit' % n1id)
453
            self._delete_network(n1id)
454
            kwargs = {param: val}
455
            print('\twith %s=%s' % (param, val))
456
            self.network1 = self._create_network(self.netname1, **kwargs)
457
            n1id = self.network1['id']
458
            self._wait_for_network(n1id, 'ACTIVE')
459
            self.network1 = self.client.get_network_details(n1id)
460
            self.assertEqual(self.network1[param], val)
461

462
    def test_connect_server(self):
463
        self.client.connect_server(self.server1['id'], self.network1['id'])
464
        self.assertTrue(self._wait_for_nic(
465
            self.network1['id'],
466
            self.server1['id']))
467

468
    def test_disconnect_server(self):
469
        self.client.disconnect_server(self.server1['id'], self.network1['id'])
470
        self.assertTrue(self._wait_for_nic(
471
            self.network1['id'],
472
            self.server1['id'],
473
            in_creation=False))
474

475
    def _test_0260_wait_for_second_network(self):
476
        self.server1 = self._create_server(
477
            self.servname1,
478
            self.flavorid,
479
            self.img)
480
        self.network2 = self._create_network(self.netname2)
481
        self._wait_for_status(self.server1['id'], 'BUILD')
482
        self._wait_for_network(self.network2['id'], 'ACTIVE')
483
        self._test_0280_list_server_nics()
484

485
    def _test_0280_list_server_nics(self):
486
        r = self.client.list_server_nics(self.server1['id'])
487
        len0 = len(r)
488
        self.client.connect_server(self.server1['id'], self.network2['id'])
489
        self.assertTrue(self._wait_for_nic(
490
            self.network2['id'],
491
            self.server1['id']))
492
        r = self.client.list_server_nics(self.server1['id'])
493
        self.assertTrue(len(r) > len0)
494

495
    def test_list_networks(self):
496
        r = self.client.list_networks()
497
        self.assertTrue(len(r) > 1)
498
        ids = [net['id'] for net in r]
499
        names = [net['name'] for net in r]
500
        self.assertTrue('1' in ids)
501
        #self.assertTrue('public' in names)
502
        self.assertTrue(self.network1['id'] in ids)
503
        self.assertTrue(self.network1['name'] in names)
504

505
        r = self.client.list_networks(detail=True)
506
        ids = [net['id'] for net in r]
507
        names = [net['name'] for net in r]
508
        for net in r:
509
            self.assertTrue(net['id'] in ids)
510
            self.assertTrue(net['name'] in names)
511
            for term in ('status', 'updated', 'created'):
512
                self.assertTrue(term in net.keys())
513

514
    def test_get_network_details(self):
515
        r = self.client.get_network_details(self.network1['id'])
516
        net1 = dict(self.network1)
517
        net1.pop('status')
518
        net1.pop('updated', None)
519
        net1.pop('attachments')
520
        r.pop('status')
521
        r.pop('updated', None)
522
        r.pop('attachments')
523
        self.assert_dicts_are_equal(net1, r)
524

525
    def test_update_network_name(self):
526
        updated_name = self.netname2 + '_upd'
527
        self.client.update_network_name(self.network2['id'], updated_name)
528

529
        def netwait(wait):
530
            r = self.client.get_network_details(self.network2['id'])
531
            if r['name'] == updated_name:
532
                return
533
            time.sleep(wait)
534
        self.do_with_progress_bar(
535
            netwait,
536
            'Network %s name is changing:' % self.network2['id'],
537
            self._waits[:5])
538

539
        r = self.client.get_network_details(self.network2['id'])
540
        self.assertEqual(r['name'], updated_name)
541

542
    def test_delete_image(self):
543
        images = self.client.list_images()
544
        self.client.delete_image(images[2]['id'])
545
        try:
546
            r = self.client.get_image_details(images[2]['id'], success=(400))
547
        except ClientError as err:
548
            self.assertEqual(err.status, 404)
549

550
    def test_create_image_metadata(self):
551
        r = self.client.create_image_metadata(self.img, 'mykey', 'myval')
552
        self.assertEqual(r['mykey'], 'myval')
553

554
    def test_update_image_metadata(self):
555
        r = self.client.create_image_metadata(self.img, 'mykey0', 'myval')
556
        r = self.client.update_image_metadata(self.img, 'mykey0', 'myval0')
557
        self.assertEqual(r['mykey0'], 'myval0')
558

559
    def test_delete_image_metadata(self):
560
        self.client.create_image_metadata(self.img, 'mykey1', 'myval1')
561
        self.client.delete_image_metadata(self.img, 'mykey1')
562
        r = self.client.get_image_metadata(self.img)
563
        self.assertNotEqual('mykey1' in r)
564
    """