blob: 11637231985154e9a72bf5808018bd9a74afa515 [file] [log] [blame]
Brian Waldonbbb1cfb2011-10-27 18:04:37 -04001import httplib2
Soren Hansenbc1d3a02011-09-08 13:33:17 +02002import json
3import os
Aaron Lee35b8c922011-10-18 17:07:19 -05004import re
Soren Hansenbc1d3a02011-09-08 13:33:17 +02005
Soren Hansenbc1d3a02011-09-08 13:33:17 +02006from kong import openstack
Soren Hansen6adacc82011-09-09 13:34:35 +02007from kong import tests
Soren Hansenbc1d3a02011-09-08 13:33:17 +02008
9
Brian Waldonbbb1cfb2011-10-27 18:04:37 -040010class TestImagesThroughCompute(tests.FunctionalTest):
Soren Hansenbc1d3a02011-09-08 13:33:17 +020011
12 def setUp(self):
Brian Waldonbbb1cfb2011-10-27 18:04:37 -040013 super(TestImagesThroughCompute, self).setUp()
Soren Hansend6b047a2011-09-09 13:39:32 +020014 self.os = openstack.Manager(self.nova)
Soren Hansenbc1d3a02011-09-08 13:33:17 +020015
Soren Hansenbc1d3a02011-09-08 13:33:17 +020016 def _assert_image_links(self, image):
17 image_id = str(image['id'])
18
Soren Hansen5f4ad832011-09-09 14:08:19 +020019 mgmt_url = self.os.nova.management_url
Aaron Lee35b8c922011-10-18 17:07:19 -050020 mgmt_url = re.sub(r'1//', r'1/', mgmt_url) # TODO: is this a bug in Nova?
Soren Hansen5f4ad832011-09-09 14:08:19 +020021 bmk_url = re.sub(r'v1.1\/', r'', mgmt_url)
Aaron Lee35b8c922011-10-18 17:07:19 -050022 self_link = {'rel': 'self',
23 'href': os.path.join(mgmt_url, 'images', image_id)}
24 bookmark_link = {'rel': 'bookmark',
25 'href': os.path.join(bmk_url, 'images', image_id)}
Soren Hansen5f4ad832011-09-09 14:08:19 +020026
Aaron Lee35b8c922011-10-18 17:07:19 -050027 self.assertIn(bookmark_link, image['links'])
28 self.assertIn(self_link, image['links'])
Soren Hansenbc1d3a02011-09-08 13:33:17 +020029
30 def _assert_image_entity_basic(self, image):
31 actual_keys = set(image.keys())
32 expected_keys = set((
33 'id',
34 'name',
35 'links',
36 ))
37 self.assertEqual(actual_keys, expected_keys)
38
39 self._assert_image_links(image)
40
41 def _assert_image_entity_detailed(self, image):
42 keys = image.keys()
43 if 'server' in keys:
44 keys.remove('server')
45 actual_keys = set(keys)
46 expected_keys = set((
Aaron Lee35b8c922011-10-18 17:07:19 -050047 'created',
Soren Hansenbc1d3a02011-09-08 13:33:17 +020048 'id',
Aaron Lee35b8c922011-10-18 17:07:19 -050049 'links',
50 'metadata',
51 'minDisk',
52 'minRam',
Soren Hansenbc1d3a02011-09-08 13:33:17 +020053 'name',
54 'progress',
Soren Hansenbc1d3a02011-09-08 13:33:17 +020055 'status',
Aaron Lee35b8c922011-10-18 17:07:19 -050056 'updated',
Soren Hansenbc1d3a02011-09-08 13:33:17 +020057 ))
58 self.assertEqual(actual_keys, expected_keys)
59
60 self._assert_image_links(image)
61
62 def test_index(self):
63 """List all images"""
64
65 response, body = self.os.nova.request('GET', '/images')
66
67 self.assertEqual(response['status'], '200')
68 resp_body = json.loads(body)
69 self.assertEqual(resp_body.keys(), ['images'])
70
71 for image in resp_body['images']:
72 self._assert_image_entity_basic(image)
Soren Hansenfce58c52011-09-09 16:07:13 +020073 test_index.tags = ['nova', 'glance']
Soren Hansenbc1d3a02011-09-08 13:33:17 +020074
75 def test_detail(self):
76 """List all images in detail"""
77
78 response, body = self.os.nova.request('GET', '/images/detail')
Soren Hansenbc1d3a02011-09-08 13:33:17 +020079 self.assertEqual(response['status'], '200')
80 resp_body = json.loads(body)
81 self.assertEqual(resp_body.keys(), ['images'])
82
83 for image in resp_body['images']:
84 self._assert_image_entity_detailed(image)
Soren Hansenfce58c52011-09-09 16:07:13 +020085 test_detail.tags = ['nova', 'glance']
Brian Waldonbbb1cfb2011-10-27 18:04:37 -040086
87
88class TestGlanceAPI(tests.FunctionalTest):
89
90 def setUp(self):
91 super(TestGlanceAPI, self).setUp()
92 self.base_url = "http://%s:%s/%s/images" % (self.glance['host'],
93 self.glance['port'],
94 self.glance['apiver'])
95
96 def test_upload_ami_style_image(self):
97 """Uploads a three-part ami-style image"""
98 aki_location = self.config['environment']['aki_location']
99 headers = {'x-image-meta-is-public': 'true',
100 'x-image-meta-name': 'test-kernel',
101 'x-image-meta-disk-format': 'aki',
102 'x-image-meta-container-format': 'aki',
103 'Content-Length': '%d' % os.path.getsize(aki_location),
104 'Content-Type': 'application/octet-stream'}
105 image_file = open(aki_location, "rb")
106 http = httplib2.Http()
107 response, content = http.request(self.base_url, 'POST',
108 headers=headers,body=image_file)
109 image_file.close()
110 self.assertEqual(201, response.status)
111 data = json.loads(content)
112 self.assertEqual(data['image']['name'], "test-kernel")
113 self.assertEqual(data['image']['checksum'],
114 self._md5sum_file(aki_location))
115 kernel_id = data['image']['id']
116
117 ari_location = self.config['environment'].get('ari_location')
118 if ari_location:
119 headers = {'x-image-meta-is-public': 'true',
120 'x-image-meta-name': 'test-ramdisk',
121 'x-image-meta-disk-format': 'ari',
122 'x-image-meta-container-format': 'ari',
123 'Content-Length': '%d' % os.path.getsize(ari_location),
124 'Content-Type': 'application/octet-stream'}
125 image_file = open(ari_location, "rb")
126 http = httplib2.Http()
127 response, content = http.request(self.base_url, 'POST',
128 headers=headers, body=image_file)
129 image_file.close()
130 self.assertEqual(201, response.status)
131 data = json.loads(content)
132 self.assertEqual(data['image']['name'], "test-ramdisk")
133 self.assertEqual(data['image']['checksum'],
134 self._md5sum_file(ari_location))
135 ramdisk_id = data['image']['id']
136 else:
137 ramdisk_id = None
138
139 ami_location = self.config['environment']['ami_location']
140 upload_data = ""
141 for chunk in self._read_in_chunks(ami_location):
142 upload_data += chunk
143 headers = {'x-image-meta-is-public': 'true',
144 'x-image-meta-name': 'test-image',
145 'x-image-meta-disk-format': 'ami',
146 'x-image-meta-container-format': 'ami',
147 'x-image-meta-property-kernel_id': kernel_id,
148 'Content-Length': '%d' % os.path.getsize(ami_location),
149 'Content-Type': 'application/octet-stream'}
150
151 if ari_location:
152 headers['x-image-meta-property-ramdisk_id'] = ramdisk_id
153
154 http = httplib2.Http()
155 response, content = http.request(self.base_url, 'POST',
156 headers=headers, body=upload_data)
157 self.assertEqual(201, response.status)
158 data = json.loads(content)
159 self.assertEqual(data['image']['name'], "test-image")
160 self.assertEqual(data['image']['checksum'],
161 self._md5sum_file(ami_location))
162 machine_id = data['image']['id']
163
164 # now ensure we can modify the image properties
165 headers = {'X-Image-Meta-Property-distro': 'Ubuntu',
166 'X-Image-Meta-Property-arch': 'x86_64',
167 'X-Image-Meta-Property-kernel_id': kernel_id}
168 if ari_location:
169 headers['X-Image-Meta-Property-ramdisk_id'] = ramdisk_id
170
171 http = httplib2.Http()
172 url = '%s/%s' % (self.base_url, machine_id)
173 response, content = http.request(url, 'PUT', headers=headers)
174 self.assertEqual(response.status, 200)
175 data = json.loads(content)
176 properties = data['image']['properties']
177 self.assertEqual(properties['arch'], "x86_64")
178 self.assertEqual(properties['distro'], "Ubuntu")
179 self.assertEqual(properties['kernel_id'], kernel_id)
180 if ari_location:
181 self.assertEqual(properties['ramdisk_id'], ramdisk_id)
182
183 # list the metadata to ensure the new values stuck
184 http = httplib2.Http()
185 response, content = http.request(url, 'HEAD')
186 self.assertEqual(response.status, 200)
187 self.assertEqual(response['x-image-meta-name'], "test-image")
188 self.assertEqual(response['x-image-meta-checksum'],
189 self._md5sum_file(ami_location))
190 self.assertEqual(response['x-image-meta-container_format'], "ami")
191 self.assertEqual(response['x-image-meta-disk_format'], "ami")
192 self.assertEqual(response['x-image-meta-property-arch'], "x86_64")
193 self.assertEqual(response['x-image-meta-property-distro'], "Ubuntu")
194 self.assertEqual(response['x-image-meta-property-kernel_id'],
195 kernel_id)
196 if ari_location:
197 self.assertEqual(response['x-image-meta-property-ramdisk_id'],
198 ramdisk_id)
199
200 # delete images for which we have non-None ids
201 delete_ids = filter(lambda x: x, (kernel_id, ramdisk_id, machine_id))
202 for image_id in delete_ids:
203 http = httplib2.Http()
204 url = '%s/%s' % (self.base_url, image_id)
205 response, content = http.request(url, 'DELETE')
206
207 test_upload_ami_style_image.tags = ['glance']