~ubuntu-branches/ubuntu/raring/glance/raring-proposed

1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3
# Copyright 2011 OpenStack, LLC
4
# All Rights Reserved.
5
#
6
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
7
#    not use this file except in compliance with the License. You may obtain
8
#    a copy of the License at
9
#
10
#         https://www.apache.org/licenses/LICENSE-2.0
11
#
12
#    Unless required by applicable law or agreed to in writing, software
13
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
#    License for the specific language governing permissions and limitations
16
#    under the License.
17
18
"""
19
Tests a Glance API server which uses an Swift backend by default
20
21
This test requires that a real Swift account is available. It looks
22
in a file GLANCE_TEST_SWIFT_CONF environ variable for the credentials to
23
use.
24
25
Note that this test clears the entire container from the Swift account
26
for use by the test case, so make sure you supply credentials for
27
test accounts only.
28
29
If a connection cannot be established, all the test cases are
30
skipped.
31
"""
32
33
import datetime
34
import hashlib
35
import httplib2
36
import json
37
import os
38
import tempfile
39
1.1.39 by Chuck Short
Import upstream version 2012.2~f2~20120621.1644
40
from glance.openstack.common import timeutils
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
41
from glance.openstack.common import uuidutils
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
42
from glance.tests import functional
43
from glance.tests.utils import skip_if_disabled, minimal_headers
44
45
FIVE_KB = 5 * 1024
46
FIVE_GB = 5 * 1024 * 1024 * 1024
47
TEST_VAR_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__),
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
48
                                            '../..', 'var'))
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
49
50
51
class TestSSL(functional.FunctionalTest):
52
53
    """Functional tests verifying SSL communication"""
54
55
    def setUp(self):
1.1.49 by Chuck Short
Import upstream version 2013.1.g3
56
        super(TestSSL, self).setUp()
57
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
58
        if getattr(self, 'inited', False):
59
            return
60
61
        self.inited = False
62
        self.disabled = True
63
64
        # Test key/cert/CA file created as per:
65
        #   http://blog.didierstevens.com/2008/12/30/
66
        #     howto-make-your-own-cert-with-openssl/
67
        # Note that for these tests certificate.crt had to
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
68
        # be created with 'Common Name' set to 127.0.0.1
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
69
70
        self.key_file = os.path.join(TEST_VAR_DIR, 'privatekey.key')
71
        if not os.path.exists(self.key_file):
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
72
            self.disabled_message = ("Could not find private key file %s" %
73
                                     self.key_file)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
74
            self.inited = True
75
            return
76
77
        self.cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
78
        if not os.path.exists(self.cert_file):
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
79
            self.disabled_message = ("Could not find certificate file %s" %
80
                                     self.cert_file)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
81
            self.inited = True
82
            return
83
84
        self.ca_file = os.path.join(TEST_VAR_DIR, 'ca.crt')
85
        if not os.path.exists(self.ca_file):
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
86
            self.disabled_message = ("Could not find CA file %s" %
87
                                     self.ca_file)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
88
            self.inited = True
89
            return
90
91
        self.inited = True
92
        self.disabled = False
93
1.1.39 by Chuck Short
Import upstream version 2012.2~f2~20120621.1644
94
    def tearDown(self):
95
        super(TestSSL, self).tearDown()
1.1.49 by Chuck Short
Import upstream version 2013.1.g3
96
        if getattr(self, 'inited', False):
97
            return
1.1.39 by Chuck Short
Import upstream version 2012.2~f2~20120621.1644
98
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
99
    @skip_if_disabled
100
    def test_get_head_simple_post(self):
101
        """
102
        We test the following sequential series of actions:
103
104
        0. GET /images
105
        - Verify no public images
106
        1. GET /images/detail
107
        - Verify no public images
108
        2. POST /images with public image named Image1
109
        and no custom properties
110
        - Verify 201 returned
111
        3. HEAD image
112
        - Verify HTTP headers have correct information we just added
113
        4. GET image
114
        - Verify all information on image we just added is correct
115
        5. GET /images
116
        - Verify the image we just added is returned
117
        6. GET /images/detail
118
        - Verify the image we just added is returned
119
        7. PUT image with custom properties of "distro" and "arch"
120
        - Verify 200 returned
121
        8. GET image
122
        - Verify updated information about image was stored
123
        9. PUT image
124
        - Remove a previously existing property.
125
        10. PUT image
126
        - Add a previously deleted property.
127
        """
128
        self.cleanup()
129
        self.start_servers(**self.__dict__.copy())
130
131
        # 0. GET /images
132
        # Verify no public images
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
133
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
134
        https = httplib2.Http(disable_ssl_certificate_validation=True)
135
        response, content = https.request(path, 'GET')
136
        self.assertEqual(response.status, 200)
137
        self.assertEqual(content, '{"images": []}')
138
139
        # 1. GET /images/detail
140
        # Verify no public images
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
141
        path = "https://%s:%d/v1/images/detail" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
142
        https = httplib2.Http(disable_ssl_certificate_validation=True)
143
        response, content = https.request(path, 'GET')
144
        self.assertEqual(response.status, 200)
145
        self.assertEqual(content, '{"images": []}')
146
147
        # 2. POST /images with public image named Image1
148
        # attribute and no custom properties. Verify a 200 OK is returned
149
        image_data = "*" * FIVE_KB
150
        headers = minimal_headers('Image1')
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
151
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
152
        https = httplib2.Http(disable_ssl_certificate_validation=True)
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
153
        response, content = https.request(path,
154
                                          'POST',
155
                                          headers=headers,
156
                                          body=image_data)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
157
        self.assertEqual(response.status, 201)
158
        data = json.loads(content)
159
        self.assertEqual(data['image']['checksum'],
160
                         hashlib.md5(image_data).hexdigest())
161
        self.assertEqual(data['image']['size'], FIVE_KB)
162
        self.assertEqual(data['image']['name'], "Image1")
163
        self.assertEqual(data['image']['is_public'], True)
164
165
        image_id = data['image']['id']
166
167
        # 3. HEAD image
168
        # Verify image found now
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
169
        path = "https://%s:%d/v1/images/%s" % ("127.0.0.1", self.api_port,
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
170
                                               image_id)
171
        https = httplib2.Http(disable_ssl_certificate_validation=True)
172
        response, content = https.request(path, 'HEAD')
173
        self.assertEqual(response.status, 200)
174
        self.assertEqual(response['x-image-meta-name'], "Image1")
175
176
        # 4. GET image
177
        # Verify all information on image we just added is correct
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
178
        path = "https://%s:%d/v1/images/%s" % ("127.0.0.1", self.api_port,
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
179
                                               image_id)
180
        https = httplib2.Http(disable_ssl_certificate_validation=True)
181
        response, content = https.request(path, 'GET')
182
        self.assertEqual(response.status, 200)
183
184
        expected_image_headers = {
185
            'x-image-meta-id': image_id,
186
            'x-image-meta-name': 'Image1',
187
            'x-image-meta-is_public': 'True',
188
            'x-image-meta-status': 'active',
189
            'x-image-meta-disk_format': 'raw',
190
            'x-image-meta-container_format': 'ovf',
191
            'x-image-meta-size': str(FIVE_KB)}
192
193
        expected_std_headers = {
194
            'content-length': str(FIVE_KB),
195
            'content-type': 'application/octet-stream'}
196
197
        for expected_key, expected_value in expected_image_headers.items():
198
            self.assertEqual(response[expected_key], expected_value,
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
199
                             "For key '%s' expected header value '%s'. "
200
                             "Got '%s'" % (expected_key,
201
                                           expected_value,
202
                                           response[expected_key]))
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
203
204
        for expected_key, expected_value in expected_std_headers.items():
205
            self.assertEqual(response[expected_key], expected_value,
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
206
                             "For key '%s' expected header value '%s'. "
207
                             "Got '%s'" % (expected_key,
208
                                           expected_value,
209
                                           response[expected_key]))
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
210
211
        self.assertEqual(content, "*" * FIVE_KB)
212
        self.assertEqual(hashlib.md5(content).hexdigest(),
213
                         hashlib.md5("*" * FIVE_KB).hexdigest())
214
215
        # 5. GET /images
216
        # Verify no public images
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
217
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
218
        https = httplib2.Http(disable_ssl_certificate_validation=True)
219
        response, content = https.request(path, 'GET')
220
        self.assertEqual(response.status, 200)
221
222
        expected_result = {"images": [
223
            {"container_format": "ovf",
224
             "disk_format": "raw",
225
             "id": image_id,
226
             "name": "Image1",
227
             "checksum": "c2e5db72bd7fd153f53ede5da5a06de3",
228
             "size": 5120}]}
229
        self.assertEqual(json.loads(content), expected_result)
230
231
        # 6. GET /images/detail
232
        # Verify image and all its metadata
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
233
        path = "https://%s:%d/v1/images/detail" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
234
        https = httplib2.Http(disable_ssl_certificate_validation=True)
235
        response, content = https.request(path, 'GET')
236
        self.assertEqual(response.status, 200)
237
238
        expected_image = {
239
            "status": "active",
240
            "name": "Image1",
241
            "deleted": False,
242
            "container_format": "ovf",
243
            "disk_format": "raw",
244
            "id": image_id,
245
            "is_public": True,
246
            "deleted_at": None,
247
            "properties": {},
248
            "size": 5120}
249
250
        image = json.loads(content)
251
252
        for expected_key, expected_value in expected_image.items():
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
253
            self.assertEqual(expected_value,
254
                             image['images'][0][expected_key],
255
                             "For key '%s' expected header value '%s'. "
256
                             "Got '%s'" % (expected_key,
257
                                           expected_value,
258
                                           image['images'][0][expected_key]))
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
259
260
        # 7. PUT image with custom properties of "distro" and "arch"
261
        # Verify 200 returned
262
        headers = {'X-Image-Meta-Property-Distro': 'Ubuntu',
263
                   'X-Image-Meta-Property-Arch': 'x86_64'}
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
264
        path = "https://%s:%d/v1/images/%s" % ("127.0.0.1", self.api_port,
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
265
                                               image_id)
266
        https = httplib2.Http(disable_ssl_certificate_validation=True)
267
        response, content = https.request(path, 'PUT', headers=headers)
268
        self.assertEqual(response.status, 200)
269
        data = json.loads(content)
270
        self.assertEqual(data['image']['properties']['arch'], "x86_64")
271
        self.assertEqual(data['image']['properties']['distro'], "Ubuntu")
272
273
        # 8. GET /images/detail
274
        # Verify image and all its metadata
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
275
        path = "https://%s:%d/v1/images/detail" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
276
        https = httplib2.Http(disable_ssl_certificate_validation=True)
277
        response, content = https.request(path, 'GET')
278
        self.assertEqual(response.status, 200)
279
280
        expected_image = {
281
            "status": "active",
282
            "name": "Image1",
283
            "deleted": False,
284
            "container_format": "ovf",
285
            "disk_format": "raw",
286
            "id": image_id,
287
            "is_public": True,
288
            "deleted_at": None,
289
            "properties": {'distro': 'Ubuntu', 'arch': 'x86_64'},
290
            "size": 5120}
291
292
        image = json.loads(content)
293
294
        for expected_key, expected_value in expected_image.items():
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
295
            self.assertEqual(expected_value,
296
                             image['images'][0][expected_key],
297
                             "For key '%s' expected header value '%s'. "
298
                             "Got '%s'" % (expected_key,
299
                                           expected_value,
300
                                           image['images'][0][expected_key]))
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
301
302
        # 9. PUT image and remove a previously existing property.
303
        headers = {'X-Image-Meta-Property-Arch': 'x86_64'}
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
304
        path = "https://%s:%d/v1/images/%s" % ("127.0.0.1", self.api_port,
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
305
                                               image_id)
306
        https = httplib2.Http(disable_ssl_certificate_validation=True)
307
        response, content = https.request(path, 'PUT', headers=headers)
308
        self.assertEqual(response.status, 200)
309
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
310
        path = "https://%s:%d/v1/images/detail" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
311
        response, content = https.request(path, 'GET')
312
        self.assertEqual(response.status, 200)
313
        data = json.loads(content)['images'][0]
314
        self.assertEqual(len(data['properties']), 1)
315
        self.assertEqual(data['properties']['arch'], "x86_64")
316
317
        # 10. PUT image and add a previously deleted property.
318
        headers = {'X-Image-Meta-Property-Distro': 'Ubuntu',
319
                   'X-Image-Meta-Property-Arch': 'x86_64'}
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
320
        path = "https://%s:%d/v1/images/%s" % ("127.0.0.1", self.api_port,
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
321
                                               image_id)
322
        https = httplib2.Http(disable_ssl_certificate_validation=True)
323
        response, content = https.request(path, 'PUT', headers=headers)
324
        self.assertEqual(response.status, 200)
325
        data = json.loads(content)
326
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
327
        path = "https://%s:%d/v1/images/detail" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
328
        response, content = https.request(path, 'GET')
329
        self.assertEqual(response.status, 200)
330
        data = json.loads(content)['images'][0]
331
        self.assertEqual(len(data['properties']), 2)
332
        self.assertEqual(data['properties']['arch'], "x86_64")
333
        self.assertEqual(data['properties']['distro'], "Ubuntu")
334
335
        self.stop_servers()
336
337
    @skip_if_disabled
338
    def test_queued_process_flow(self):
339
        """
340
        We test the process flow where a user registers an image
341
        with Glance but does not immediately upload an image file.
342
        Later, the user uploads an image file using a PUT operation.
343
        We track the changing of image status throughout this process.
344
345
        0. GET /images
346
        - Verify no public images
347
        1. POST /images with public image named Image1 with no location
348
           attribute and no image data.
349
        - Verify 201 returned
350
        2. GET /images
351
        - Verify one public image
352
        3. HEAD image
353
        - Verify image now in queued status
354
        4. PUT image with image data
355
        - Verify 200 returned
356
        5. HEAD image
357
        - Verify image now in active status
358
        6. GET /images
359
        - Verify one public image
360
        """
361
362
        self.cleanup()
363
        self.start_servers(**self.__dict__.copy())
364
365
        # 0. GET /images
366
        # Verify no public images
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
367
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
368
        https = httplib2.Http(disable_ssl_certificate_validation=True)
369
        response, content = https.request(path, 'GET')
370
        self.assertEqual(response.status, 200)
371
        self.assertEqual(content, '{"images": []}')
372
373
        # 1. POST /images with public image named Image1
374
        # with no location or image data
375
        headers = minimal_headers('Image1')
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
376
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
377
        https = httplib2.Http(disable_ssl_certificate_validation=True)
378
        response, content = https.request(path, 'POST', headers=headers)
379
        self.assertEqual(response.status, 201)
380
        data = json.loads(content)
381
        self.assertEqual(data['image']['checksum'], None)
382
        self.assertEqual(data['image']['size'], 0)
383
        self.assertEqual(data['image']['container_format'], 'ovf')
384
        self.assertEqual(data['image']['disk_format'], 'raw')
385
        self.assertEqual(data['image']['name'], "Image1")
386
        self.assertEqual(data['image']['is_public'], True)
387
388
        image_id = data['image']['id']
389
390
        # 2. GET /images
391
        # Verify 1 public image
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
392
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
393
        https = httplib2.Http(disable_ssl_certificate_validation=True)
394
        response, content = https.request(path, 'GET')
395
        self.assertEqual(response.status, 200)
396
        data = json.loads(content)
397
        self.assertEqual(data['images'][0]['id'], image_id)
398
        self.assertEqual(data['images'][0]['checksum'], None)
399
        self.assertEqual(data['images'][0]['size'], 0)
400
        self.assertEqual(data['images'][0]['container_format'], 'ovf')
401
        self.assertEqual(data['images'][0]['disk_format'], 'raw')
402
        self.assertEqual(data['images'][0]['name'], "Image1")
403
404
        # 3. HEAD /images
405
        # Verify status is in queued
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
406
        path = "https://%s:%d/v1/images/%s" % ("127.0.0.1", self.api_port,
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
407
                                               image_id)
408
        https = httplib2.Http(disable_ssl_certificate_validation=True)
409
        response, content = https.request(path, 'HEAD')
410
        self.assertEqual(response.status, 200)
411
        self.assertEqual(response['x-image-meta-name'], "Image1")
412
        self.assertEqual(response['x-image-meta-status'], "queued")
413
        self.assertEqual(response['x-image-meta-size'], '0')
414
        self.assertEqual(response['x-image-meta-id'], image_id)
415
416
        # 4. PUT image with image data, verify 200 returned
417
        image_data = "*" * FIVE_KB
418
        headers = {'Content-Type': 'application/octet-stream'}
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
419
        path = "https://%s:%d/v1/images/%s" % ("127.0.0.1", self.api_port,
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
420
                                               image_id)
421
        https = httplib2.Http(disable_ssl_certificate_validation=True)
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
422
        response, content = https.request(path,
423
                                          'PUT',
424
                                          headers=headers,
425
                                          body=image_data)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
426
        self.assertEqual(response.status, 200)
427
        data = json.loads(content)
428
        self.assertEqual(data['image']['checksum'],
429
                         hashlib.md5(image_data).hexdigest())
430
        self.assertEqual(data['image']['size'], FIVE_KB)
431
        self.assertEqual(data['image']['name'], "Image1")
432
        self.assertEqual(data['image']['is_public'], True)
433
434
        # 5. HEAD image
435
        # Verify status is in active
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
436
        path = "https://%s:%d/v1/images/%s" % ("127.0.0.1", self.api_port,
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
437
                                               image_id)
438
        https = httplib2.Http(disable_ssl_certificate_validation=True)
439
        response, content = https.request(path, 'HEAD')
440
        self.assertEqual(response.status, 200)
441
        self.assertEqual(response['x-image-meta-name'], "Image1")
442
        self.assertEqual(response['x-image-meta-status'], "active")
443
444
        # 6. GET /images
445
        # Verify 1 public image still...
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
446
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
447
        https = httplib2.Http(disable_ssl_certificate_validation=True)
448
        response, content = https.request(path, 'GET')
449
        self.assertEqual(response.status, 200)
450
        data = json.loads(content)
451
        self.assertEqual(data['images'][0]['checksum'],
452
                         hashlib.md5(image_data).hexdigest())
453
        self.assertEqual(data['images'][0]['id'], image_id)
454
        self.assertEqual(data['images'][0]['size'], FIVE_KB)
455
        self.assertEqual(data['images'][0]['container_format'], 'ovf')
456
        self.assertEqual(data['images'][0]['disk_format'], 'raw')
457
        self.assertEqual(data['images'][0]['name'], "Image1")
458
459
        self.stop_servers()
460
461
    @skip_if_disabled
462
    def test_version_variations(self):
463
        """
464
        We test that various calls to the images and root endpoints are
465
        handled properly, and that usage of the Accept: header does
466
        content negotiation properly.
467
        """
468
469
        self.cleanup()
470
        self.start_servers(**self.__dict__.copy())
471
472
        versions = {'versions': [{
1.1.50 by Chuck Short
Import upstream version 2013.1~rc1
473
            "id": "v2.1",
474
            "status": "CURRENT",
475
            "links": [{
476
                "rel": "self",
477
                "href": "https://127.0.0.1:%d/v2/" % self.api_port}]}, {
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
478
            "id": "v2.0",
1.1.50 by Chuck Short
Import upstream version 2013.1~rc1
479
            "status": "SUPPORTED",
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
480
            "links": [{
481
                "rel": "self",
482
                "href": "https://127.0.0.1:%d/v2/" % self.api_port}]}, {
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
483
            "id": "v1.1",
484
            "status": "CURRENT",
485
            "links": [{
486
                "rel": "self",
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
487
                "href": "https://127.0.0.1:%d/v1/" % self.api_port}]}, {
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
488
            "id": "v1.0",
489
            "status": "SUPPORTED",
490
            "links": [{
491
                "rel": "self",
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
492
                "href": "https://127.0.0.1:%d/v1/" % self.api_port}]}]}
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
493
        versions_json = json.dumps(versions)
494
        images = {'images': []}
495
        images_json = json.dumps(images)
496
497
        # 0. GET / with no Accept: header
498
        # Verify version choices returned.
499
        # Bug lp:803260  no Accept header causes a 500 in glance-api
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
500
        path = "https://%s:%d/" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
501
        https = httplib2.Http(disable_ssl_certificate_validation=True)
502
        response, content = https.request(path, 'GET')
503
        self.assertEqual(response.status, 300)
504
        self.assertEqual(content, versions_json)
505
506
        # 1. GET /images with no Accept: header
507
        # Verify version choices returned.
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
508
        path = "https://%s:%d/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
509
        https = httplib2.Http(disable_ssl_certificate_validation=True)
510
        response, content = https.request(path, 'GET')
511
        self.assertEqual(response.status, 300)
512
        self.assertEqual(content, versions_json)
513
514
        # 2. GET /v1/images with no Accept: header
515
        # Verify empty images list returned.
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
516
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
517
        https = httplib2.Http(disable_ssl_certificate_validation=True)
518
        response, content = https.request(path, 'GET')
519
        self.assertEqual(response.status, 200)
520
        self.assertEqual(content, images_json)
521
522
        # 3. GET / with Accept: unknown header
523
        # Verify version choices returned. Verify message in API log about
524
        # unknown accept header.
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
525
        path = "https://%s:%d/" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
526
        https = httplib2.Http(disable_ssl_certificate_validation=True)
527
        headers = {'Accept': 'unknown'}
528
        response, content = https.request(path, 'GET', headers=headers)
529
        self.assertEqual(response.status, 300)
530
        self.assertEqual(content, versions_json)
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
531
        self.assertTrue('Unknown version. Returning version choices'
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
532
                        in open(self.api_server.log_file).read())
533
534
        # 4. GET / with an Accept: application/vnd.openstack.images-v1
535
        # Verify empty image list returned
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
536
        path = "https://%s:%d/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
537
        https = httplib2.Http(disable_ssl_certificate_validation=True)
538
        headers = {'Accept': 'application/vnd.openstack.images-v1'}
539
        response, content = https.request(path, 'GET', headers=headers)
540
        self.assertEqual(response.status, 200)
541
        self.assertEqual(content, images_json)
542
543
        # 5. GET /images with a Accept: application/vnd.openstack.compute-v1
544
        # header. Verify version choices returned. Verify message in API log
545
        # about unknown accept header.
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
546
        path = "https://%s:%d/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
547
        https = httplib2.Http(disable_ssl_certificate_validation=True)
548
        headers = {'Accept': 'application/vnd.openstack.compute-v1'}
549
        response, content = https.request(path, 'GET', headers=headers)
550
        self.assertEqual(response.status, 300)
551
        self.assertEqual(content, versions_json)
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
552
        self.assertTrue('Unknown version. Returning version choices'
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
553
                        in open(self.api_server.log_file).read())
554
555
        # 6. GET /v1.0/images with no Accept: header
556
        # Verify empty image list returned
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
557
        path = "https://%s:%d/v1.0/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
558
        https = httplib2.Http(disable_ssl_certificate_validation=True)
559
        response, content = https.request(path, 'GET')
560
        self.assertEqual(response.status, 200)
561
        self.assertEqual(content, images_json)
562
563
        # 7. GET /v1.a/images with no Accept: header
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
564
        # Verify versions list returned
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
565
        path = "https://%s:%d/v1.a/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
566
        https = httplib2.Http(disable_ssl_certificate_validation=True)
567
        response, content = https.request(path, 'GET')
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
568
        self.assertEqual(response.status, 300)
569
        self.assertEqual(content, versions_json)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
570
571
        # 8. GET /va.1/images with no Accept: header
572
        # Verify version choices returned
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
573
        path = "https://%s:%d/va.1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
574
        https = httplib2.Http(disable_ssl_certificate_validation=True)
575
        response, content = https.request(path, 'GET')
576
        self.assertEqual(response.status, 300)
577
        self.assertEqual(content, versions_json)
578
579
        # 9. GET /versions with no Accept: header
580
        # Verify version choices returned
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
581
        path = "https://%s:%d/versions" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
582
        https = httplib2.Http(disable_ssl_certificate_validation=True)
583
        response, content = https.request(path, 'GET')
584
        self.assertEqual(response.status, 300)
585
        self.assertEqual(content, versions_json)
586
587
        # 10. GET /versions with a Accept: application/vnd.openstack.images-v1
588
        # header. Verify version choices returned.
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
589
        path = "https://%s:%d/versions" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
590
        https = httplib2.Http(disable_ssl_certificate_validation=True)
591
        headers = {'Accept': 'application/vnd.openstack.images-v1'}
592
        response, content = https.request(path, 'GET', headers=headers)
593
        self.assertEqual(response.status, 300)
594
        self.assertEqual(content, versions_json)
595
596
        # 11. GET /v1/versions with no Accept: header
597
        # Verify 404 returned
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
598
        path = "https://%s:%d/v1/versions" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
599
        https = httplib2.Http(disable_ssl_certificate_validation=True)
600
        response, content = https.request(path, 'GET')
601
        self.assertEqual(response.status, 404)
602
603
        # 12. GET /v2/versions with no Accept: header
604
        # Verify version choices returned
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
605
        path = "https://%s:%d/v2/versions" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
606
        https = httplib2.Http(disable_ssl_certificate_validation=True)
607
        response, content = https.request(path, 'GET')
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
608
        self.assertEqual(response.status, 404)
609
610
        # 12b. GET /v3/versions with no Accept: header (where v3 in unknown)
611
        # Verify version choices returned
612
        path = "https://%s:%d/v3/versions" % ("127.0.0.1", self.api_port)
613
        https = httplib2.Http(disable_ssl_certificate_validation=True)
614
        response, content = https.request(path, 'GET')
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
615
        self.assertEqual(response.status, 300)
616
        self.assertEqual(content, versions_json)
617
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
618
        # 13. GET /images with a Accept: application/vnd.openstack.compute-v3
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
619
        # header. Verify version choices returned. Verify message in API log
620
        # about unknown version in accept header.
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
621
        path = "https://%s:%d/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
622
        https = httplib2.Http(disable_ssl_certificate_validation=True)
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
623
        headers = {'Accept': 'application/vnd.openstack.images-v3'}
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
624
        response, content = https.request(path, 'GET', headers=headers)
625
        self.assertEqual(response.status, 300)
626
        self.assertEqual(content, versions_json)
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
627
        self.assertTrue('Unknown version. Returning version choices'
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
628
                        in open(self.api_server.log_file).read())
629
630
        # 14. GET /v1.2/images with no Accept: header
631
        # Verify version choices returned
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
632
        path = "https://%s:%d/v1.2/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
633
        https = httplib2.Http(disable_ssl_certificate_validation=True)
634
        response, content = https.request(path, 'GET')
635
        self.assertEqual(response.status, 300)
636
        self.assertEqual(content, versions_json)
637
638
        self.stop_servers()
639
640
    @skip_if_disabled
641
    def test_size_greater_2G_mysql(self):
642
        """
643
        A test against the actual datastore backend for the registry
644
        to ensure that the image size property is not truncated.
645
646
        :see https://bugs.launchpad.net/glance/+bug/739433
647
        """
648
649
        self.cleanup()
650
        self.start_servers(**self.__dict__.copy())
651
652
        # 1. POST /images with public image named Image1
653
        # attribute and a size of 5G. Use the HTTP engine with an
654
        # X-Image-Meta-Location attribute to make Glance forego
655
        # "adding" the image data.
656
        # Verify a 201 OK is returned
657
        headers = minimal_headers('Image1')
658
        headers['X-Image-Meta-Location'] = 'https://example.com/fakeimage'
659
        headers['X-Image-Meta-Size'] = str(FIVE_GB)
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
660
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
661
        https = httplib2.Http(disable_ssl_certificate_validation=True)
662
        response, content = https.request(path, 'POST', headers=headers)
663
        self.assertEqual(response.status, 201)
664
665
        # 2. HEAD /images
666
        # Verify image size is what was passed in, and not truncated
667
        path = response.get('location')
668
        https = httplib2.Http(disable_ssl_certificate_validation=True)
669
        response, content = https.request(path, 'HEAD')
670
        self.assertEqual(response.status, 200)
671
        self.assertEqual(response['x-image-meta-size'], str(FIVE_GB))
672
        self.assertEqual(response['x-image-meta-name'], 'Image1')
673
        self.assertEqual(response['x-image-meta-is_public'], 'True')
674
675
        self.stop_servers()
676
677
    @skip_if_disabled
678
    def test_traceback_not_consumed(self):
679
        """
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
680
        A test that errors coming from the POST API do not get consumed
681
        and print the actual error message, and
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
682
        not something like <traceback object at 0x1918d40>
683
684
        :see https://bugs.launchpad.net/glance/+bug/755912
685
        """
686
        self.cleanup()
687
        self.start_servers(**self.__dict__.copy())
688
689
        # POST /images with binary data, but not setting
690
        # Content-Type to application/octet-stream, verify a
691
        # 400 returned and that the error is readable.
692
        with tempfile.NamedTemporaryFile() as test_data_file:
693
            test_data_file.write("XXX")
694
            test_data_file.flush()
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
695
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
696
        headers = {'X-Image-Meta-Name': 'Image1',
697
                   'X-Image-Meta-Container-Format': 'ovf',
698
                   'X-Image-Meta-Disk-Format': 'vdi'}
699
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
700
        https = httplib2.Http(disable_ssl_certificate_validation=True)
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
701
        response, content = https.request(path,
702
                                          'POST',
703
                                          headers=headers,
704
                                          body=test_data_file.name)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
705
        self.assertEqual(response.status, 400)
706
        expected = "Content-Type must be application/octet-stream"
707
        self.assertTrue(expected in content,
708
                        "Could not find '%s' in '%s'" % (expected, content))
709
710
        self.stop_servers()
711
712
    @skip_if_disabled
713
    def test_filtered_images(self):
714
        """
715
        Set up four test images and ensure each query param filter works
716
        """
717
        self.cleanup()
718
        self.start_servers(**self.__dict__.copy())
719
720
        # 0. GET /images
721
        # Verify no public images
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
722
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
723
        https = httplib2.Http(disable_ssl_certificate_validation=True)
724
        response, content = https.request(path, 'GET')
725
        self.assertEqual(response.status, 200)
726
        self.assertEqual(content, '{"images": []}')
727
728
        # 1. POST /images with three public images, and one private image
729
        # with various attributes
730
        headers = {'Content-Type': 'application/octet-stream',
731
                   'X-Image-Meta-Name': 'Image1',
732
                   'X-Image-Meta-Status': 'active',
733
                   'X-Image-Meta-Container-Format': 'ovf',
734
                   'X-Image-Meta-Disk-Format': 'vdi',
735
                   'X-Image-Meta-Size': '19',
736
                   'X-Image-Meta-Is-Public': 'True',
737
                   'X-Image-Meta-Property-pants': 'are on'}
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
738
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
739
        https = httplib2.Http(disable_ssl_certificate_validation=True)
740
        response, content = https.request(path, 'POST', headers=headers)
741
        self.assertEqual(response.status, 201)
742
        data = json.loads(content)
743
        self.assertEqual(data['image']['properties']['pants'], "are on")
744
        self.assertEqual(data['image']['is_public'], True)
745
746
        headers = {'Content-Type': 'application/octet-stream',
747
                   'X-Image-Meta-Name': 'My Image!',
748
                   'X-Image-Meta-Status': 'active',
749
                   'X-Image-Meta-Container-Format': 'ovf',
750
                   'X-Image-Meta-Disk-Format': 'vhd',
751
                   'X-Image-Meta-Size': '20',
752
                   'X-Image-Meta-Is-Public': 'True',
753
                   'X-Image-Meta-Property-pants': 'are on'}
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
754
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
755
        https = httplib2.Http(disable_ssl_certificate_validation=True)
756
        response, content = https.request(path, 'POST', headers=headers)
757
        self.assertEqual(response.status, 201)
758
        data = json.loads(content)
759
        self.assertEqual(data['image']['properties']['pants'], "are on")
760
        self.assertEqual(data['image']['is_public'], True)
761
762
        headers = {'Content-Type': 'application/octet-stream',
763
                   'X-Image-Meta-Name': 'My Image!',
764
                   'X-Image-Meta-Status': 'saving',
765
                   'X-Image-Meta-Container-Format': 'ami',
766
                   'X-Image-Meta-Disk-Format': 'ami',
767
                   'X-Image-Meta-Size': '21',
768
                   'X-Image-Meta-Is-Public': 'True',
769
                   'X-Image-Meta-Property-pants': 'are off'}
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
770
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
771
        https = httplib2.Http(disable_ssl_certificate_validation=True)
772
        response, content = https.request(path, 'POST', headers=headers)
773
        self.assertEqual(response.status, 201)
774
        data = json.loads(content)
775
        self.assertEqual(data['image']['properties']['pants'], "are off")
776
        self.assertEqual(data['image']['is_public'], True)
777
778
        headers = {'Content-Type': 'application/octet-stream',
779
                   'X-Image-Meta-Name': 'My Private Image',
780
                   'X-Image-Meta-Status': 'active',
781
                   'X-Image-Meta-Container-Format': 'ami',
782
                   'X-Image-Meta-Disk-Format': 'ami',
783
                   'X-Image-Meta-Size': '22',
784
                   'X-Image-Meta-Is-Public': 'False'}
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
785
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
786
        https = httplib2.Http(disable_ssl_certificate_validation=True)
787
        response, content = https.request(path, 'POST', headers=headers)
788
        self.assertEqual(response.status, 201)
789
        data = json.loads(content)
790
        self.assertEqual(data['image']['is_public'], False)
791
792
        # 2. GET /images
793
        # Verify three public images
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
794
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
795
        response, content = https.request(path, 'GET')
796
        self.assertEqual(response.status, 200)
797
        data = json.loads(content)
798
        self.assertEqual(len(data['images']), 3)
799
800
        # 3. GET /images with name filter
801
        # Verify correct images returned with name
802
        params = "name=My%20Image!"
803
        path = "https://%s:%d/v1/images?%s" % (
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
804
               "127.0.0.1", self.api_port, params)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
805
        response, content = https.request(path, 'GET')
806
        self.assertEqual(response.status, 200)
807
        data = json.loads(content)
808
        self.assertEqual(len(data['images']), 2)
809
        for image in data['images']:
810
            self.assertEqual(image['name'], "My Image!")
811
812
        # 4. GET /images with status filter
813
        # Verify correct images returned with status
814
        params = "status=queued"
815
        path = "https://%s:%d/v1/images/detail?%s" % (
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
816
               "127.0.0.1", self.api_port, params)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
817
        response, content = https.request(path, 'GET')
818
        self.assertEqual(response.status, 200)
819
        data = json.loads(content)
820
        self.assertEqual(len(data['images']), 3)
821
        for image in data['images']:
822
            self.assertEqual(image['status'], "queued")
823
824
        params = "status=active"
825
        path = "https://%s:%d/v1/images/detail?%s" % (
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
826
               "127.0.0.1", self.api_port, params)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
827
        response, content = https.request(path, 'GET')
828
        self.assertEqual(response.status, 200)
829
        data = json.loads(content)
830
        self.assertEqual(len(data['images']), 0)
831
832
        # 5. GET /images with container_format filter
833
        # Verify correct images returned with container_format
834
        params = "container_format=ovf"
835
        path = "https://%s:%d/v1/images?%s" % (
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
836
               "127.0.0.1", self.api_port, params)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
837
        response, content = https.request(path, 'GET')
838
        self.assertEqual(response.status, 200)
839
        data = json.loads(content)
840
        self.assertEqual(len(data['images']), 2)
841
        for image in data['images']:
842
            self.assertEqual(image['container_format'], "ovf")
843
844
        # 6. GET /images with disk_format filter
845
        # Verify correct images returned with disk_format
846
        params = "disk_format=vdi"
847
        path = "https://%s:%d/v1/images?%s" % (
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
848
               "127.0.0.1", self.api_port, params)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
849
        response, content = https.request(path, 'GET')
850
        self.assertEqual(response.status, 200)
851
        data = json.loads(content)
852
        self.assertEqual(len(data['images']), 1)
853
        for image in data['images']:
854
            self.assertEqual(image['disk_format'], "vdi")
855
856
        # 7. GET /images with size_max filter
857
        # Verify correct images returned with size <= expected
858
        params = "size_max=20"
859
        path = "https://%s:%d/v1/images?%s" % (
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
860
               "127.0.0.1", self.api_port, params)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
861
        response, content = https.request(path, 'GET')
862
        self.assertEqual(response.status, 200)
863
        data = json.loads(content)
864
        self.assertEqual(len(data['images']), 2)
865
        for image in data['images']:
866
            self.assertTrue(image['size'] <= 20)
867
868
        # 8. GET /images with size_min filter
869
        # Verify correct images returned with size >= expected
870
        params = "size_min=20"
871
        path = "https://%s:%d/v1/images?%s" % (
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
872
               "127.0.0.1", self.api_port, params)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
873
        response, content = https.request(path, 'GET')
874
        self.assertEqual(response.status, 200)
875
        data = json.loads(content)
876
        self.assertEqual(len(data['images']), 2)
877
        for image in data['images']:
878
            self.assertTrue(image['size'] >= 20)
879
880
        # 9. Get /images with is_public=None filter
881
        # Verify correct images returned with property
882
        # Bug lp:803656  Support is_public in filtering
883
        params = "is_public=None"
884
        path = "https://%s:%d/v1/images?%s" % (
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
885
               "127.0.0.1", self.api_port, params)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
886
        response, content = https.request(path, 'GET')
887
        self.assertEqual(response.status, 200)
888
        data = json.loads(content)
889
        self.assertEqual(len(data['images']), 4)
890
891
        # 10. Get /images with is_public=False filter
892
        # Verify correct images returned with property
893
        # Bug lp:803656  Support is_public in filtering
894
        params = "is_public=False"
895
        path = "https://%s:%d/v1/images?%s" % (
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
896
               "127.0.0.1", self.api_port, params)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
897
        response, content = https.request(path, 'GET')
898
        self.assertEqual(response.status, 200)
899
        data = json.loads(content)
900
        self.assertEqual(len(data['images']), 1)
901
        for image in data['images']:
902
            self.assertEqual(image['name'], "My Private Image")
903
904
        # 11. Get /images with is_public=True filter
905
        # Verify correct images returned with property
906
        # Bug lp:803656  Support is_public in filtering
907
        params = "is_public=True"
908
        path = "https://%s:%d/v1/images?%s" % (
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
909
               "127.0.0.1", self.api_port, params)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
910
        response, content = https.request(path, 'GET')
911
        self.assertEqual(response.status, 200)
912
        data = json.loads(content)
913
        self.assertEqual(len(data['images']), 3)
914
        for image in data['images']:
915
            self.assertNotEqual(image['name'], "My Private Image")
916
917
        # 12. GET /images with property filter
918
        # Verify correct images returned with property
919
        params = "property-pants=are%20on"
920
        path = "https://%s:%d/v1/images/detail?%s" % (
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
921
               "127.0.0.1", self.api_port, params)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
922
        response, content = https.request(path, 'GET')
923
        self.assertEqual(response.status, 200)
924
        data = json.loads(content)
925
        self.assertEqual(len(data['images']), 2)
926
        for image in data['images']:
927
            self.assertEqual(image['properties']['pants'], "are on")
928
929
        # 13. GET /images with property filter and name filter
930
        # Verify correct images returned with property and name
931
        # Make sure you quote the url when using more than one param!
932
        params = "name=My%20Image!&property-pants=are%20on"
933
        path = "https://%s:%d/v1/images/detail?%s" % (
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
934
                "127.0.0.1", self.api_port, params)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
935
        response, content = https.request(path, 'GET')
936
        self.assertEqual(response.status, 200)
937
        data = json.loads(content)
938
        self.assertEqual(len(data['images']), 1)
939
        for image in data['images']:
940
            self.assertEqual(image['properties']['pants'], "are on")
941
            self.assertEqual(image['name'], "My Image!")
942
943
        # 14. GET /images with past changes-since filter
1.1.39 by Chuck Short
Import upstream version 2012.2~f2~20120621.1644
944
        dt1 = timeutils.utcnow() - datetime.timedelta(1)
945
        iso1 = timeutils.isotime(dt1)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
946
        params = "changes-since=%s" % iso1
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
947
        path = "https://%s:%d/v1/images?%s" % ("127.0.0.1",
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
948
                                               self.api_port, params)
949
        response, content = https.request(path, 'GET')
950
        self.assertEqual(response.status, 200)
951
        data = json.loads(content)
952
        self.assertEqual(len(data['images']), 3)
953
954
        # 15. GET /images with future changes-since filter
1.1.39 by Chuck Short
Import upstream version 2012.2~f2~20120621.1644
955
        dt2 = timeutils.utcnow() + datetime.timedelta(1)
956
        iso2 = timeutils.isotime(dt2)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
957
        params = "changes-since=%s" % iso2
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
958
        path = "https://%s:%d/v1/images?%s" % ("127.0.0.1",
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
959
                                               self.api_port, params)
960
        response, content = https.request(path, 'GET')
961
        self.assertEqual(response.status, 200)
962
        data = json.loads(content)
963
        self.assertEqual(len(data['images']), 0)
964
965
        self.stop_servers()
966
967
    @skip_if_disabled
968
    def test_limited_images(self):
969
        """
970
        Ensure marker and limit query params work
971
        """
972
        self.cleanup()
973
        self.start_servers(**self.__dict__.copy())
974
975
        # 0. GET /images
976
        # Verify no public images
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
977
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
978
        https = httplib2.Http(disable_ssl_certificate_validation=True)
979
        response, content = https.request(path, 'GET')
980
        self.assertEqual(response.status, 200)
981
        self.assertEqual(content, '{"images": []}')
982
983
        # 1. POST /images with three public images with various attributes
984
        headers = minimal_headers('Image1')
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
985
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
986
        https = httplib2.Http(disable_ssl_certificate_validation=True)
987
        response, content = https.request(path, 'POST', headers=headers)
988
        self.assertEqual(response.status, 201)
989
        data = json.loads(content)
990
991
        image_ids = [data['image']['id']]
992
993
        headers = minimal_headers('Image2')
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
994
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
995
        https = httplib2.Http(disable_ssl_certificate_validation=True)
996
        response, content = https.request(path, 'POST', headers=headers)
997
        self.assertEqual(response.status, 201)
998
        data = json.loads(content)
999
1000
        image_ids.append(data['image']['id'])
1001
1002
        headers = minimal_headers('Image3')
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
1003
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
1004
        https = httplib2.Http(disable_ssl_certificate_validation=True)
1005
        response, content = https.request(path, 'POST', headers=headers)
1006
        self.assertEqual(response.status, 201)
1007
        data = json.loads(content)
1008
1009
        image_ids.append(data['image']['id'])
1010
1011
        # 2. GET /images with limit of 2
1012
        # Verify only two images were returned
1013
        params = "limit=2"
1014
        path = "https://%s:%d/v1/images?%s" % (
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
1015
               "127.0.0.1", self.api_port, params)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
1016
        response, content = https.request(path, 'GET')
1017
        self.assertEqual(response.status, 200)
1018
        data = json.loads(content)
1019
        self.assertEqual(len(data['images']), 2)
1020
        self.assertEqual(data['images'][0]['id'], image_ids[2])
1021
        self.assertEqual(data['images'][1]['id'], image_ids[1])
1022
1023
        # 3. GET /images with marker
1024
        # Verify only two images were returned
1025
        params = "marker=%s" % image_ids[2]
1026
        path = "https://%s:%d/v1/images?%s" % (
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
1027
               "127.0.0.1", self.api_port, params)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
1028
        response, content = https.request(path, 'GET')
1029
        self.assertEqual(response.status, 200)
1030
        data = json.loads(content)
1031
        self.assertEqual(len(data['images']), 2)
1032
        self.assertEqual(data['images'][0]['id'], image_ids[1])
1033
        self.assertEqual(data['images'][1]['id'], image_ids[0])
1034
1035
        # 4. GET /images with marker and limit
1036
        # Verify only one image was returned with the correct id
1037
        params = "limit=1&marker=%s" % image_ids[1]
1038
        path = "https://%s:%d/v1/images?%s" % (
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
1039
               "127.0.0.1", self.api_port, params)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
1040
        response, content = https.request(path, 'GET')
1041
        self.assertEqual(response.status, 200)
1042
        data = json.loads(content)
1043
        self.assertEqual(len(data['images']), 1)
1044
        self.assertEqual(data['images'][0]['id'], image_ids[0])
1045
1046
        # 5. GET /images/detail with marker and limit
1047
        # Verify only one image was returned with the correct id
1048
        params = "limit=1&marker=%s" % image_ids[2]
1049
        path = "https://%s:%d/v1/images?%s" % (
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
1050
               "127.0.0.1", self.api_port, params)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
1051
        response, content = https.request(path, 'GET')
1052
        self.assertEqual(response.status, 200)
1053
        data = json.loads(content)
1054
        self.assertEqual(len(data['images']), 1)
1055
        self.assertEqual(data['images'][0]['id'], image_ids[1])
1056
1057
        self.stop_servers()
1058
1059
    @skip_if_disabled
1060
    def test_ordered_images(self):
1061
        """
1062
        Set up three test images and ensure each query param filter works
1063
        """
1064
        self.cleanup()
1065
        self.start_servers(**self.__dict__.copy())
1066
1067
        # 0. GET /images
1068
        # Verify no public images
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
1069
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
1070
        https = httplib2.Http(disable_ssl_certificate_validation=True)
1071
        response, content = https.request(path, 'GET')
1072
        self.assertEqual(response.status, 200)
1073
        self.assertEqual(content, '{"images": []}')
1074
1075
        # 1. POST /images with three public images with various attributes
1076
        headers = {'Content-Type': 'application/octet-stream',
1077
                   'X-Image-Meta-Name': 'Image1',
1078
                   'X-Image-Meta-Status': 'active',
1079
                   'X-Image-Meta-Container-Format': 'ovf',
1080
                   'X-Image-Meta-Disk-Format': 'vdi',
1081
                   'X-Image-Meta-Size': '19',
1082
                   'X-Image-Meta-Is-Public': 'True'}
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
1083
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
1084
        https = httplib2.Http(disable_ssl_certificate_validation=True)
1085
        response, content = https.request(path, 'POST', headers=headers)
1086
        self.assertEqual(response.status, 201)
1087
        data = json.loads(content)
1088
1089
        image_ids = [data['image']['id']]
1090
1091
        headers = {'Content-Type': 'application/octet-stream',
1092
                   'X-Image-Meta-Name': 'ASDF',
1093
                   'X-Image-Meta-Status': 'active',
1094
                   'X-Image-Meta-Container-Format': 'bare',
1095
                   'X-Image-Meta-Disk-Format': 'iso',
1096
                   'X-Image-Meta-Size': '2',
1097
                   'X-Image-Meta-Is-Public': 'True'}
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
1098
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
1099
        https = httplib2.Http(disable_ssl_certificate_validation=True)
1100
        response, content = https.request(path, 'POST', headers=headers)
1101
        self.assertEqual(response.status, 201)
1102
        data = json.loads(content)
1103
1104
        image_ids.append(data['image']['id'])
1105
1106
        headers = {'Content-Type': 'application/octet-stream',
1107
                   'X-Image-Meta-Name': 'XYZ',
1108
                   'X-Image-Meta-Status': 'saving',
1109
                   'X-Image-Meta-Container-Format': 'ami',
1110
                   'X-Image-Meta-Disk-Format': 'ami',
1111
                   'X-Image-Meta-Size': '5',
1112
                   'X-Image-Meta-Is-Public': 'True'}
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
1113
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
1114
        https = httplib2.Http(disable_ssl_certificate_validation=True)
1115
        response, content = https.request(path, 'POST', headers=headers)
1116
        self.assertEqual(response.status, 201)
1117
        data = json.loads(content)
1118
1119
        image_ids.append(data['image']['id'])
1120
1121
        # 2. GET /images with no query params
1122
        # Verify three public images sorted by created_at desc
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
1123
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
1124
        https = httplib2.Http(disable_ssl_certificate_validation=True)
1125
        response, content = https.request(path, 'GET')
1126
        self.assertEqual(response.status, 200)
1127
        data = json.loads(content)
1128
        self.assertEqual(len(data['images']), 3)
1129
        self.assertEqual(data['images'][0]['id'], image_ids[2])
1130
        self.assertEqual(data['images'][1]['id'], image_ids[1])
1131
        self.assertEqual(data['images'][2]['id'], image_ids[0])
1132
1133
        # 3. GET /images sorted by name asc
1134
        params = 'sort_key=name&sort_dir=asc'
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
1135
        path = "https://%s:%d/v1/images?%s" % ("127.0.0.1",
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
1136
                                               self.api_port, params)
1137
        https = httplib2.Http(disable_ssl_certificate_validation=True)
1138
        response, content = https.request(path, 'GET')
1139
        self.assertEqual(response.status, 200)
1140
        data = json.loads(content)
1141
        self.assertEqual(len(data['images']), 3)
1142
        self.assertEqual(data['images'][0]['id'], image_ids[1])
1143
        self.assertEqual(data['images'][1]['id'], image_ids[0])
1144
        self.assertEqual(data['images'][2]['id'], image_ids[2])
1145
1146
        # 4. GET /images sorted by size desc
1147
        params = 'sort_key=size&sort_dir=desc'
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
1148
        path = "https://%s:%d/v1/images?%s" % ("127.0.0.1",
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
1149
                                               self.api_port, params)
1150
        https = httplib2.Http(disable_ssl_certificate_validation=True)
1151
        response, content = https.request(path, 'GET')
1152
        self.assertEqual(response.status, 200)
1153
        data = json.loads(content)
1154
        self.assertEqual(len(data['images']), 3)
1155
        self.assertEqual(data['images'][0]['id'], image_ids[0])
1156
        self.assertEqual(data['images'][1]['id'], image_ids[2])
1157
        self.assertEqual(data['images'][2]['id'], image_ids[1])
1158
        # 5. GET /images sorted by size desc with a marker
1159
        params = 'sort_key=size&sort_dir=desc&marker=%s' % image_ids[0]
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
1160
        path = "https://%s:%d/v1/images?%s" % ("127.0.0.1",
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
1161
                                               self.api_port, params)
1162
        https = httplib2.Http(disable_ssl_certificate_validation=True)
1163
        response, content = https.request(path, 'GET')
1164
        self.assertEqual(response.status, 200)
1165
        data = json.loads(content)
1166
        self.assertEqual(len(data['images']), 2)
1167
        self.assertEqual(data['images'][0]['id'], image_ids[2])
1168
        self.assertEqual(data['images'][1]['id'], image_ids[1])
1169
1170
        # 6. GET /images sorted by name asc with a marker
1171
        params = 'sort_key=name&sort_dir=asc&marker=%s' % image_ids[2]
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
1172
        path = "https://%s:%d/v1/images?%s" % ("127.0.0.1",
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
1173
                                               self.api_port, params)
1174
        https = httplib2.Http(disable_ssl_certificate_validation=True)
1175
        response, content = https.request(path, 'GET')
1176
        self.assertEqual(response.status, 200)
1177
        data = json.loads(content)
1178
        self.assertEqual(len(data['images']), 0)
1179
1180
        self.stop_servers()
1181
1182
    @skip_if_disabled
1183
    def test_duplicate_image_upload(self):
1184
        """
1185
        Upload initial image, then attempt to upload duplicate image
1186
        """
1187
        self.cleanup()
1188
        self.start_servers(**self.__dict__.copy())
1189
1190
        # 0. GET /images
1191
        # Verify no public images
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
1192
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
1193
        https = httplib2.Http(disable_ssl_certificate_validation=True)
1194
        response, content = https.request(path, 'GET')
1195
        self.assertEqual(response.status, 200)
1196
        self.assertEqual(content, '{"images": []}')
1197
1198
        # 1. POST /images with public image named Image1
1199
        headers = {'Content-Type': 'application/octet-stream',
1200
                   'X-Image-Meta-Name': 'Image1',
1201
                   'X-Image-Meta-Status': 'active',
1202
                   'X-Image-Meta-Container-Format': 'ovf',
1203
                   'X-Image-Meta-Disk-Format': 'vdi',
1204
                   'X-Image-Meta-Size': '19',
1205
                   'X-Image-Meta-Is-Public': 'True'}
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
1206
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
1207
        https = httplib2.Http(disable_ssl_certificate_validation=True)
1208
        response, content = https.request(path, 'POST', headers=headers)
1209
        self.assertEqual(response.status, 201)
1210
        data = json.loads(content)
1211
1212
        image_id = data['image']['id']
1213
1214
        # 2. POST /images with public image named Image1, and ID: 1
1215
        headers = {'Content-Type': 'application/octet-stream',
1216
                   'X-Image-Meta-Name': 'Image1 Update',
1217
                   'X-Image-Meta-Status': 'active',
1218
                   'X-Image-Meta-Container-Format': 'ovf',
1219
                   'X-Image-Meta-Disk-Format': 'vdi',
1220
                   'X-Image-Meta-Size': '19',
1221
                   'X-Image-Meta-Id': image_id,
1222
                   'X-Image-Meta-Is-Public': 'True'}
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
1223
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
1224
        https = httplib2.Http(disable_ssl_certificate_validation=True)
1225
        response, content = https.request(path, 'POST', headers=headers)
1226
        self.assertEqual(response.status, 409)
1227
        expected = "An image with identifier %s already exists" % image_id
1228
        self.assertTrue(expected in content,
1229
                        "Could not find '%s' in '%s'" % (expected, content))
1230
1231
        self.stop_servers()
1232
1233
    @skip_if_disabled
1234
    def test_delete_not_existing(self):
1235
        """
1236
        We test the following:
1237
1238
        0. GET /images
1239
        - Verify no public images
1240
        1. DELETE random image
1241
        - Verify 404
1242
        """
1243
        self.cleanup()
1244
        self.start_servers(**self.__dict__.copy())
1245
1246
        # 0. GET /images
1247
        # Verify no public images
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
1248
        path = "https://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
1249
        https = httplib2.Http(disable_ssl_certificate_validation=True)
1250
        response, content = https.request(path, 'GET')
1251
        self.assertEqual(response.status, 200)
1252
        self.assertEqual(content, '{"images": []}')
1253
1254
        # 1. DELETE /images/1
1255
        # Verify 404 returned
1.1.41 by Chuck Short
Import upstream version 2012.2~f3
1256
        path = "https://%s:%d/v1/images/%s" % ("127.0.0.1", self.api_port,
1.1.47 by Chuck Short
Import upstream version 2013.1~g1
1257
                                               uuidutils.generate_uuid())
1.1.37 by Adam Gandelman
Import upstream version 2012.2~f2~20120524.1541
1258
        https = httplib2.Http(disable_ssl_certificate_validation=True)
1259
        response, content = https.request(path, 'DELETE')
1260
        self.assertEqual(response.status, 404)
1261
1262
        self.stop_servers()