Merge lp:~rackspace-titan/nova/minram-mindisk into lp:~hudson-openstack/nova/trunk
- minram-mindisk
- Merge into trunk
Status: | Rejected | ||||
---|---|---|---|---|---|
Rejected by: | Brian Waldon | ||||
Proposed branch: | lp:~rackspace-titan/nova/minram-mindisk | ||||
Merge into: | lp:~hudson-openstack/nova/trunk | ||||
Diff against target: |
557 lines (+327/-1) 10 files modified
nova/api/openstack/create_instance_helper.py (+4/-0) nova/api/openstack/images.py (+6/-0) nova/api/openstack/schemas/v1.1/image.rng (+6/-0) nova/api/openstack/views/images.py (+5/-0) nova/compute/api.py (+5/-0) nova/exception.py (+8/-0) nova/image/glance.py (+1/-1) nova/tests/api/openstack/test_images.py (+189/-0) nova/tests/image/test_glance.py (+12/-0) nova/tests/test_compute.py (+91/-0) |
||||
To merge this branch: | bzr merge lp:~rackspace-titan/nova/minram-mindisk | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Dan Prince (community) | Approve | ||
Chris Behrens (community) | Approve | ||
Brian Waldon (community) | Approve | ||
Review via email: mp+76491@code.launchpad.net |
Commit message
Description of the change
This addresses Bug #819990 Add minDisk minRam to OSAPI image details. It also enforces the minram and mindisk constraints if they exist. Corresponding tests have been added.
Naveed Massjouni (ironcamel) wrote : | # |
Good point. Fixed.
Chris Behrens (cbehrens) wrote : | # |
Looks good. Minor thing. I'd like to see the tests that call compute_
Alex Meade (alex-meade) wrote : | # |
good point, I am on it
Brian Waldon (bcwaldon) wrote : | # |
Merged through gerrit.
Unmerged revisions
- 1585. By Alex Meade
-
Added the deleting of servers that were created in tests
- 1584. By Alex Meade
-
fixed incorrect exception names
- 1583. By Naveed Massjouni
-
Changing FlavorMemoryToo
Small/FlavorDis kTooSmall exceptions to
InstanceTypeMemoryTooSmall/ InstanceTypeDis kTooSmall. - 1582. By Naveed Massjouni
-
pep8
- 1581. By Naveed Massjouni
-
More tests.
- 1580. By Naveed Massjouni
-
Adding tests for minram/mindisk.
- 1579. By Naveed Massjouni
-
Honor the min_ram and min_disk attributes of images when creating a server
- 1578. By Naveed Massjouni
-
removing print
- 1577. By Naveed Massjouni
-
Merge from trunk
- 1576. By Alex Meade
-
Added support for filtering images with minRam and minDisk
Preview Diff
1 | === modified file 'nova/api/openstack/create_instance_helper.py' | |||
2 | --- nova/api/openstack/create_instance_helper.py 2011-09-15 14:07:58 +0000 | |||
3 | +++ nova/api/openstack/create_instance_helper.py 2011-09-22 19:53:25 +0000 | |||
4 | @@ -187,6 +187,10 @@ | |||
5 | 187 | config_drive=config_drive,)) | 187 | config_drive=config_drive,)) |
6 | 188 | except quota.QuotaError as error: | 188 | except quota.QuotaError as error: |
7 | 189 | self._handle_quota_error(error) | 189 | self._handle_quota_error(error) |
8 | 190 | except exception.InstanceTypeMemoryTooSmall as error: | ||
9 | 191 | raise exc.HTTPBadRequest(explanation=unicode(error)) | ||
10 | 192 | except exception.InstanceTypeDiskTooSmall as error: | ||
11 | 193 | raise exc.HTTPBadRequest(explanation=unicode(error)) | ||
12 | 190 | except exception.ImageNotFound as error: | 194 | except exception.ImageNotFound as error: |
13 | 191 | msg = _("Can not find requested image") | 195 | msg = _("Can not find requested image") |
14 | 192 | raise exc.HTTPBadRequest(explanation=msg) | 196 | raise exc.HTTPBadRequest(explanation=msg) |
15 | 193 | 197 | ||
16 | === modified file 'nova/api/openstack/images.py' | |||
17 | --- nova/api/openstack/images.py 2011-09-20 21:11:49 +0000 | |||
18 | +++ nova/api/openstack/images.py 2011-09-22 19:53:25 +0000 | |||
19 | @@ -41,6 +41,8 @@ | |||
20 | 41 | 'changes-since': 'changes-since', | 41 | 'changes-since': 'changes-since', |
21 | 42 | 'server': 'property-instance_ref', | 42 | 'server': 'property-instance_ref', |
22 | 43 | 'type': 'property-image_type', | 43 | 'type': 'property-image_type', |
23 | 44 | 'minRam': 'min_ram', | ||
24 | 45 | 'minDisk': 'min_disk', | ||
25 | 44 | } | 46 | } |
26 | 45 | 47 | ||
27 | 46 | 48 | ||
28 | @@ -239,6 +241,10 @@ | |||
29 | 239 | image_elem.set('status', str(image_dict['status'])) | 241 | image_elem.set('status', str(image_dict['status'])) |
30 | 240 | if 'progress' in image_dict: | 242 | if 'progress' in image_dict: |
31 | 241 | image_elem.set('progress', str(image_dict['progress'])) | 243 | image_elem.set('progress', str(image_dict['progress'])) |
32 | 244 | if 'minRam' in image_dict: | ||
33 | 245 | image_elem.set('minRam', str(image_dict['minRam'])) | ||
34 | 246 | if 'minDisk' in image_dict: | ||
35 | 247 | image_elem.set('minDisk', str(image_dict['minDisk'])) | ||
36 | 242 | if 'server' in image_dict: | 248 | if 'server' in image_dict: |
37 | 243 | server_elem = self._create_server_node(image_dict['server']) | 249 | server_elem = self._create_server_node(image_dict['server']) |
38 | 244 | image_elem.append(server_elem) | 250 | image_elem.append(server_elem) |
39 | 245 | 251 | ||
40 | === modified file 'nova/api/openstack/schemas/v1.1/image.rng' | |||
41 | --- nova/api/openstack/schemas/v1.1/image.rng 2011-08-25 16:05:53 +0000 | |||
42 | +++ nova/api/openstack/schemas/v1.1/image.rng 2011-09-22 19:53:25 +0000 | |||
43 | @@ -9,6 +9,12 @@ | |||
44 | 9 | <attribute name="progress"> <text/> </attribute> | 9 | <attribute name="progress"> <text/> </attribute> |
45 | 10 | </optional> | 10 | </optional> |
46 | 11 | <optional> | 11 | <optional> |
47 | 12 | <attribute name="minDisk"> <text/> </attribute> | ||
48 | 13 | </optional> | ||
49 | 14 | <optional> | ||
50 | 15 | <attribute name="minRam"> <text/> </attribute> | ||
51 | 16 | </optional> | ||
52 | 17 | <optional> | ||
53 | 12 | <element name="server"> | 18 | <element name="server"> |
54 | 13 | <attribute name="id"> <text/> </attribute> | 19 | <attribute name="id"> <text/> </attribute> |
55 | 14 | <zeroOrMore> | 20 | <zeroOrMore> |
56 | 15 | 21 | ||
57 | === modified file 'nova/api/openstack/views/images.py' | |||
58 | --- nova/api/openstack/views/images.py 2011-09-20 20:21:06 +0000 | |||
59 | +++ nova/api/openstack/views/images.py 2011-09-22 19:53:25 +0000 | |||
60 | @@ -161,6 +161,11 @@ | |||
61 | 161 | 161 | ||
62 | 162 | if detail: | 162 | if detail: |
63 | 163 | image["metadata"] = image_obj.get("properties", {}) | 163 | image["metadata"] = image_obj.get("properties", {}) |
64 | 164 | if 'min_ram' in image_obj: | ||
65 | 165 | image["minRam"] = image_obj.get("min_ram") or 0 | ||
66 | 166 | |||
67 | 167 | if 'min_disk' in image_obj: | ||
68 | 168 | image["minDisk"] = image_obj.get("min_disk") or 0 | ||
69 | 164 | 169 | ||
70 | 165 | return image | 170 | return image |
71 | 166 | 171 | ||
72 | 167 | 172 | ||
73 | === modified file 'nova/compute/api.py' | |||
74 | --- nova/compute/api.py 2011-09-21 21:00:53 +0000 | |||
75 | +++ nova/compute/api.py 2011-09-22 19:53:25 +0000 | |||
76 | @@ -219,6 +219,11 @@ | |||
77 | 219 | image_href) | 219 | image_href) |
78 | 220 | image = image_service.show(context, image_id) | 220 | image = image_service.show(context, image_id) |
79 | 221 | 221 | ||
80 | 222 | if instance_type['memory_mb'] < int(image.get('min_ram', 0)): | ||
81 | 223 | raise exception.InstanceTypeMemoryTooSmall() | ||
82 | 224 | if instance_type['local_gb'] < int(image.get('min_disk', 0)): | ||
83 | 225 | raise exception.InstanceTypeDiskTooSmall() | ||
84 | 226 | |||
85 | 222 | config_drive_id = None | 227 | config_drive_id = None |
86 | 223 | if config_drive and config_drive is not True: | 228 | if config_drive and config_drive is not True: |
87 | 224 | # config_drive is volume id | 229 | # config_drive is volume id |
88 | 225 | 230 | ||
89 | === modified file 'nova/exception.py' | |||
90 | --- nova/exception.py 2011-09-16 02:53:42 +0000 | |||
91 | +++ nova/exception.py 2011-09-22 19:53:25 +0000 | |||
92 | @@ -810,3 +810,11 @@ | |||
93 | 810 | if message is None: | 810 | if message is None: |
94 | 811 | message = _("1 or more Zones could not complete the request") | 811 | message = _("1 or more Zones could not complete the request") |
95 | 812 | super(ZoneRequestError, self).__init__(message=message) | 812 | super(ZoneRequestError, self).__init__(message=message) |
96 | 813 | |||
97 | 814 | |||
98 | 815 | class InstanceTypeMemoryTooSmall(NovaException): | ||
99 | 816 | message = _("Instance type's memory is too small for requested image.") | ||
100 | 817 | |||
101 | 818 | |||
102 | 819 | class InstanceTypeDiskTooSmall(NovaException): | ||
103 | 820 | message = _("Instance type's disk is too small for requested image.") | ||
104 | 813 | 821 | ||
105 | === modified file 'nova/image/glance.py' | |||
106 | --- nova/image/glance.py 2011-09-20 18:56:15 +0000 | |||
107 | +++ nova/image/glance.py 2011-09-22 19:53:25 +0000 | |||
108 | @@ -404,7 +404,7 @@ | |||
109 | 404 | 'container_format', 'checksum', 'id', | 404 | 'container_format', 'checksum', 'id', |
110 | 405 | 'name', 'created_at', 'updated_at', | 405 | 'name', 'created_at', 'updated_at', |
111 | 406 | 'deleted_at', 'deleted', 'status', | 406 | 'deleted_at', 'deleted', 'status', |
113 | 407 | 'is_public'] | 407 | 'min_disk', 'min_ram', 'is_public'] |
114 | 408 | output = {} | 408 | output = {} |
115 | 409 | for attr in IMAGE_ATTRIBUTES: | 409 | for attr in IMAGE_ATTRIBUTES: |
116 | 410 | output[attr] = image_meta.get(attr) | 410 | output[attr] = image_meta.get(attr) |
117 | 411 | 411 | ||
118 | === modified file 'nova/tests/api/openstack/test_images.py' | |||
119 | --- nova/tests/api/openstack/test_images.py 2011-09-21 20:17:05 +0000 | |||
120 | +++ nova/tests/api/openstack/test_images.py 2011-09-22 19:53:25 +0000 | |||
121 | @@ -113,6 +113,7 @@ | |||
122 | 113 | self.assertDictMatch(expected_image, actual_image) | 113 | self.assertDictMatch(expected_image, actual_image) |
123 | 114 | 114 | ||
124 | 115 | def test_get_image_v1_1(self): | 115 | def test_get_image_v1_1(self): |
125 | 116 | self.maxDiff = None | ||
126 | 116 | request = webob.Request.blank('/v1.1/fake/images/124') | 117 | request = webob.Request.blank('/v1.1/fake/images/124') |
127 | 117 | app = fakes.wsgi_app(fake_auth_context=self._get_fake_context()) | 118 | app = fakes.wsgi_app(fake_auth_context=self._get_fake_context()) |
128 | 118 | response = request.get_response(app) | 119 | response = request.get_response(app) |
129 | @@ -133,6 +134,8 @@ | |||
130 | 133 | "created": NOW_API_FORMAT, | 134 | "created": NOW_API_FORMAT, |
131 | 134 | "status": "SAVING", | 135 | "status": "SAVING", |
132 | 135 | "progress": 0, | 136 | "progress": 0, |
133 | 137 | "minDisk": 0, | ||
134 | 138 | "minRam": 0, | ||
135 | 136 | 'server': { | 139 | 'server': { |
136 | 137 | 'id': '42', | 140 | 'id': '42', |
137 | 138 | "links": [{ | 141 | "links": [{ |
138 | @@ -542,6 +545,8 @@ | |||
139 | 542 | 'created': NOW_API_FORMAT, | 545 | 'created': NOW_API_FORMAT, |
140 | 543 | 'status': 'ACTIVE', | 546 | 'status': 'ACTIVE', |
141 | 544 | 'progress': 100, | 547 | 'progress': 100, |
142 | 548 | 'minDisk': 0, | ||
143 | 549 | 'minRam': 0, | ||
144 | 545 | "links": [{ | 550 | "links": [{ |
145 | 546 | "rel": "self", | 551 | "rel": "self", |
146 | 547 | "href": "http://localhost/v1.1/fake/images/123", | 552 | "href": "http://localhost/v1.1/fake/images/123", |
147 | @@ -567,6 +572,8 @@ | |||
148 | 567 | 'created': NOW_API_FORMAT, | 572 | 'created': NOW_API_FORMAT, |
149 | 568 | 'status': 'SAVING', | 573 | 'status': 'SAVING', |
150 | 569 | 'progress': 0, | 574 | 'progress': 0, |
151 | 575 | 'minDisk': 0, | ||
152 | 576 | 'minRam': 0, | ||
153 | 570 | 'server': { | 577 | 'server': { |
154 | 571 | 'id': '42', | 578 | 'id': '42', |
155 | 572 | "links": [{ | 579 | "links": [{ |
156 | @@ -603,6 +610,8 @@ | |||
157 | 603 | 'created': NOW_API_FORMAT, | 610 | 'created': NOW_API_FORMAT, |
158 | 604 | 'status': 'SAVING', | 611 | 'status': 'SAVING', |
159 | 605 | 'progress': 0, | 612 | 'progress': 0, |
160 | 613 | 'minDisk': 0, | ||
161 | 614 | 'minRam': 0, | ||
162 | 606 | 'server': { | 615 | 'server': { |
163 | 607 | 'id': '42', | 616 | 'id': '42', |
164 | 608 | "links": [{ | 617 | "links": [{ |
165 | @@ -639,6 +648,8 @@ | |||
166 | 639 | 'created': NOW_API_FORMAT, | 648 | 'created': NOW_API_FORMAT, |
167 | 640 | 'status': 'ACTIVE', | 649 | 'status': 'ACTIVE', |
168 | 641 | 'progress': 100, | 650 | 'progress': 100, |
169 | 651 | 'minDisk': 0, | ||
170 | 652 | 'minRam': 0, | ||
171 | 642 | 'server': { | 653 | 'server': { |
172 | 643 | 'id': '42', | 654 | 'id': '42', |
173 | 644 | "links": [{ | 655 | "links": [{ |
174 | @@ -675,6 +686,8 @@ | |||
175 | 675 | 'created': NOW_API_FORMAT, | 686 | 'created': NOW_API_FORMAT, |
176 | 676 | 'status': 'ERROR', | 687 | 'status': 'ERROR', |
177 | 677 | 'progress': 0, | 688 | 'progress': 0, |
178 | 689 | 'minDisk': 0, | ||
179 | 690 | 'minRam': 0, | ||
180 | 678 | 'server': { | 691 | 'server': { |
181 | 679 | 'id': '42', | 692 | 'id': '42', |
182 | 680 | "links": [{ | 693 | "links": [{ |
183 | @@ -711,6 +724,8 @@ | |||
184 | 711 | 'created': NOW_API_FORMAT, | 724 | 'created': NOW_API_FORMAT, |
185 | 712 | 'status': 'DELETED', | 725 | 'status': 'DELETED', |
186 | 713 | 'progress': 0, | 726 | 'progress': 0, |
187 | 727 | 'minDisk': 0, | ||
188 | 728 | 'minRam': 0, | ||
189 | 714 | 'server': { | 729 | 'server': { |
190 | 715 | 'id': '42', | 730 | 'id': '42', |
191 | 716 | "links": [{ | 731 | "links": [{ |
192 | @@ -747,6 +762,8 @@ | |||
193 | 747 | 'created': NOW_API_FORMAT, | 762 | 'created': NOW_API_FORMAT, |
194 | 748 | 'status': 'DELETED', | 763 | 'status': 'DELETED', |
195 | 749 | 'progress': 0, | 764 | 'progress': 0, |
196 | 765 | 'minDisk': 0, | ||
197 | 766 | 'minRam': 0, | ||
198 | 750 | 'server': { | 767 | 'server': { |
199 | 751 | 'id': '42', | 768 | 'id': '42', |
200 | 752 | "links": [{ | 769 | "links": [{ |
201 | @@ -780,6 +797,8 @@ | |||
202 | 780 | 'created': NOW_API_FORMAT, | 797 | 'created': NOW_API_FORMAT, |
203 | 781 | 'status': 'ACTIVE', | 798 | 'status': 'ACTIVE', |
204 | 782 | 'progress': 100, | 799 | 'progress': 100, |
205 | 800 | 'minDisk': 0, | ||
206 | 801 | 'minRam': 0, | ||
207 | 783 | "links": [{ | 802 | "links": [{ |
208 | 784 | "rel": "self", | 803 | "rel": "self", |
209 | 785 | "href": "http://localhost/v1.1/fake/images/130", | 804 | "href": "http://localhost/v1.1/fake/images/130", |
210 | @@ -810,6 +829,30 @@ | |||
211 | 810 | controller.index(request) | 829 | controller.index(request) |
212 | 811 | self.mox.VerifyAll() | 830 | self.mox.VerifyAll() |
213 | 812 | 831 | ||
214 | 832 | def test_image_filter_with_min_ram(self): | ||
215 | 833 | image_service = self.mox.CreateMockAnything() | ||
216 | 834 | context = self._get_fake_context() | ||
217 | 835 | filters = {'min_ram': '0'} | ||
218 | 836 | image_service.index(context, filters=filters).AndReturn([]) | ||
219 | 837 | self.mox.ReplayAll() | ||
220 | 838 | request = webob.Request.blank('/v1.1/images?minRam=0') | ||
221 | 839 | request.environ['nova.context'] = context | ||
222 | 840 | controller = images.ControllerV11(image_service=image_service) | ||
223 | 841 | controller.index(request) | ||
224 | 842 | self.mox.VerifyAll() | ||
225 | 843 | |||
226 | 844 | def test_image_filter_with_min_disk(self): | ||
227 | 845 | image_service = self.mox.CreateMockAnything() | ||
228 | 846 | context = self._get_fake_context() | ||
229 | 847 | filters = {'min_disk': '7'} | ||
230 | 848 | image_service.index(context, filters=filters).AndReturn([]) | ||
231 | 849 | self.mox.ReplayAll() | ||
232 | 850 | request = webob.Request.blank('/v1.1/images?minDisk=7') | ||
233 | 851 | request.environ['nova.context'] = context | ||
234 | 852 | controller = images.ControllerV11(image_service=image_service) | ||
235 | 853 | controller.index(request) | ||
236 | 854 | self.mox.VerifyAll() | ||
237 | 855 | |||
238 | 813 | def test_image_filter_with_status(self): | 856 | def test_image_filter_with_status(self): |
239 | 814 | image_service = self.mox.CreateMockAnything() | 857 | image_service = self.mox.CreateMockAnything() |
240 | 815 | context = self._get_fake_context() | 858 | context = self._get_fake_context() |
241 | @@ -1369,6 +1412,152 @@ | |||
242 | 1369 | server_root = root.find('{0}server'.format(NS)) | 1412 | server_root = root.find('{0}server'.format(NS)) |
243 | 1370 | self.assertEqual(server_root, None) | 1413 | self.assertEqual(server_root, None) |
244 | 1371 | 1414 | ||
245 | 1415 | def test_show_with_min_ram(self): | ||
246 | 1416 | serializer = images.ImageXMLSerializer() | ||
247 | 1417 | |||
248 | 1418 | fixture = { | ||
249 | 1419 | 'image': { | ||
250 | 1420 | 'id': 1, | ||
251 | 1421 | 'name': 'Image1', | ||
252 | 1422 | 'created': self.TIMESTAMP, | ||
253 | 1423 | 'updated': self.TIMESTAMP, | ||
254 | 1424 | 'status': 'ACTIVE', | ||
255 | 1425 | 'progress': 80, | ||
256 | 1426 | 'minRam': 256, | ||
257 | 1427 | 'server': { | ||
258 | 1428 | 'id': '1', | ||
259 | 1429 | 'links': [ | ||
260 | 1430 | { | ||
261 | 1431 | 'href': self.SERVER_HREF, | ||
262 | 1432 | 'rel': 'self', | ||
263 | 1433 | }, | ||
264 | 1434 | { | ||
265 | 1435 | 'href': self.SERVER_BOOKMARK, | ||
266 | 1436 | 'rel': 'bookmark', | ||
267 | 1437 | }, | ||
268 | 1438 | ], | ||
269 | 1439 | }, | ||
270 | 1440 | 'metadata': { | ||
271 | 1441 | 'key1': 'value1', | ||
272 | 1442 | }, | ||
273 | 1443 | 'links': [ | ||
274 | 1444 | { | ||
275 | 1445 | 'href': self.IMAGE_HREF % 1, | ||
276 | 1446 | 'rel': 'self', | ||
277 | 1447 | }, | ||
278 | 1448 | { | ||
279 | 1449 | 'href': self.IMAGE_BOOKMARK % 1, | ||
280 | 1450 | 'rel': 'bookmark', | ||
281 | 1451 | }, | ||
282 | 1452 | ], | ||
283 | 1453 | }, | ||
284 | 1454 | } | ||
285 | 1455 | |||
286 | 1456 | output = serializer.serialize(fixture, 'show') | ||
287 | 1457 | print output | ||
288 | 1458 | root = etree.XML(output) | ||
289 | 1459 | xmlutil.validate_schema(root, 'image') | ||
290 | 1460 | image_dict = fixture['image'] | ||
291 | 1461 | |||
292 | 1462 | for key in ['name', 'id', 'updated', 'created', 'status', 'progress', | ||
293 | 1463 | 'minRam']: | ||
294 | 1464 | self.assertEqual(root.get(key), str(image_dict[key])) | ||
295 | 1465 | |||
296 | 1466 | link_nodes = root.findall('{0}link'.format(ATOMNS)) | ||
297 | 1467 | self.assertEqual(len(link_nodes), 2) | ||
298 | 1468 | for i, link in enumerate(image_dict['links']): | ||
299 | 1469 | for key, value in link.items(): | ||
300 | 1470 | self.assertEqual(link_nodes[i].get(key), value) | ||
301 | 1471 | |||
302 | 1472 | metadata_root = root.find('{0}metadata'.format(NS)) | ||
303 | 1473 | metadata_elems = metadata_root.findall('{0}meta'.format(NS)) | ||
304 | 1474 | self.assertEqual(len(metadata_elems), 1) | ||
305 | 1475 | for i, metadata_elem in enumerate(metadata_elems): | ||
306 | 1476 | (meta_key, meta_value) = image_dict['metadata'].items()[i] | ||
307 | 1477 | self.assertEqual(str(metadata_elem.get('key')), str(meta_key)) | ||
308 | 1478 | self.assertEqual(str(metadata_elem.text).strip(), str(meta_value)) | ||
309 | 1479 | |||
310 | 1480 | server_root = root.find('{0}server'.format(NS)) | ||
311 | 1481 | self.assertEqual(server_root.get('id'), image_dict['server']['id']) | ||
312 | 1482 | link_nodes = server_root.findall('{0}link'.format(ATOMNS)) | ||
313 | 1483 | self.assertEqual(len(link_nodes), 2) | ||
314 | 1484 | for i, link in enumerate(image_dict['server']['links']): | ||
315 | 1485 | for key, value in link.items(): | ||
316 | 1486 | self.assertEqual(link_nodes[i].get(key), value) | ||
317 | 1487 | |||
318 | 1488 | def test_show_with_min_disk(self): | ||
319 | 1489 | serializer = images.ImageXMLSerializer() | ||
320 | 1490 | |||
321 | 1491 | fixture = { | ||
322 | 1492 | 'image': { | ||
323 | 1493 | 'id': 1, | ||
324 | 1494 | 'name': 'Image1', | ||
325 | 1495 | 'created': self.TIMESTAMP, | ||
326 | 1496 | 'updated': self.TIMESTAMP, | ||
327 | 1497 | 'status': 'ACTIVE', | ||
328 | 1498 | 'progress': 80, | ||
329 | 1499 | 'minDisk': 5, | ||
330 | 1500 | 'server': { | ||
331 | 1501 | 'id': '1', | ||
332 | 1502 | 'links': [ | ||
333 | 1503 | { | ||
334 | 1504 | 'href': self.SERVER_HREF, | ||
335 | 1505 | 'rel': 'self', | ||
336 | 1506 | }, | ||
337 | 1507 | { | ||
338 | 1508 | 'href': self.SERVER_BOOKMARK, | ||
339 | 1509 | 'rel': 'bookmark', | ||
340 | 1510 | }, | ||
341 | 1511 | ], | ||
342 | 1512 | }, | ||
343 | 1513 | 'metadata': { | ||
344 | 1514 | 'key1': 'value1', | ||
345 | 1515 | }, | ||
346 | 1516 | 'links': [ | ||
347 | 1517 | { | ||
348 | 1518 | 'href': self.IMAGE_HREF % 1, | ||
349 | 1519 | 'rel': 'self', | ||
350 | 1520 | }, | ||
351 | 1521 | { | ||
352 | 1522 | 'href': self.IMAGE_BOOKMARK % 1, | ||
353 | 1523 | 'rel': 'bookmark', | ||
354 | 1524 | }, | ||
355 | 1525 | ], | ||
356 | 1526 | }, | ||
357 | 1527 | } | ||
358 | 1528 | |||
359 | 1529 | output = serializer.serialize(fixture, 'show') | ||
360 | 1530 | print output | ||
361 | 1531 | root = etree.XML(output) | ||
362 | 1532 | xmlutil.validate_schema(root, 'image') | ||
363 | 1533 | image_dict = fixture['image'] | ||
364 | 1534 | |||
365 | 1535 | for key in ['name', 'id', 'updated', 'created', 'status', 'progress', | ||
366 | 1536 | 'minDisk']: | ||
367 | 1537 | self.assertEqual(root.get(key), str(image_dict[key])) | ||
368 | 1538 | |||
369 | 1539 | link_nodes = root.findall('{0}link'.format(ATOMNS)) | ||
370 | 1540 | self.assertEqual(len(link_nodes), 2) | ||
371 | 1541 | for i, link in enumerate(image_dict['links']): | ||
372 | 1542 | for key, value in link.items(): | ||
373 | 1543 | self.assertEqual(link_nodes[i].get(key), value) | ||
374 | 1544 | |||
375 | 1545 | metadata_root = root.find('{0}metadata'.format(NS)) | ||
376 | 1546 | metadata_elems = metadata_root.findall('{0}meta'.format(NS)) | ||
377 | 1547 | self.assertEqual(len(metadata_elems), 1) | ||
378 | 1548 | for i, metadata_elem in enumerate(metadata_elems): | ||
379 | 1549 | (meta_key, meta_value) = image_dict['metadata'].items()[i] | ||
380 | 1550 | self.assertEqual(str(metadata_elem.get('key')), str(meta_key)) | ||
381 | 1551 | self.assertEqual(str(metadata_elem.text).strip(), str(meta_value)) | ||
382 | 1552 | |||
383 | 1553 | server_root = root.find('{0}server'.format(NS)) | ||
384 | 1554 | self.assertEqual(server_root.get('id'), image_dict['server']['id']) | ||
385 | 1555 | link_nodes = server_root.findall('{0}link'.format(ATOMNS)) | ||
386 | 1556 | self.assertEqual(len(link_nodes), 2) | ||
387 | 1557 | for i, link in enumerate(image_dict['server']['links']): | ||
388 | 1558 | for key, value in link.items(): | ||
389 | 1559 | self.assertEqual(link_nodes[i].get(key), value) | ||
390 | 1560 | |||
391 | 1372 | def test_index(self): | 1561 | def test_index(self): |
392 | 1373 | serializer = images.ImageXMLSerializer() | 1562 | serializer = images.ImageXMLSerializer() |
393 | 1374 | 1563 | ||
394 | 1375 | 1564 | ||
395 | === modified file 'nova/tests/image/test_glance.py' | |||
396 | --- nova/tests/image/test_glance.py 2011-09-20 18:56:15 +0000 | |||
397 | +++ nova/tests/image/test_glance.py 2011-09-22 19:53:25 +0000 | |||
398 | @@ -127,6 +127,8 @@ | |||
399 | 127 | 'name': 'test image', | 127 | 'name': 'test image', |
400 | 128 | 'is_public': False, | 128 | 'is_public': False, |
401 | 129 | 'size': None, | 129 | 'size': None, |
402 | 130 | 'min_disk': None, | ||
403 | 131 | 'min_ram': None, | ||
404 | 130 | 'location': None, | 132 | 'location': None, |
405 | 131 | 'disk_format': None, | 133 | 'disk_format': None, |
406 | 132 | 'container_format': None, | 134 | 'container_format': None, |
407 | @@ -157,6 +159,8 @@ | |||
408 | 157 | 'name': 'test image', | 159 | 'name': 'test image', |
409 | 158 | 'is_public': False, | 160 | 'is_public': False, |
410 | 159 | 'size': None, | 161 | 'size': None, |
411 | 162 | 'min_disk': None, | ||
412 | 163 | 'min_ram': None, | ||
413 | 160 | 'location': None, | 164 | 'location': None, |
414 | 161 | 'disk_format': None, | 165 | 'disk_format': None, |
415 | 162 | 'container_format': None, | 166 | 'container_format': None, |
416 | @@ -287,6 +291,8 @@ | |||
417 | 287 | 'name': 'TestImage %d' % (i), | 291 | 'name': 'TestImage %d' % (i), |
418 | 288 | 'properties': {}, | 292 | 'properties': {}, |
419 | 289 | 'size': None, | 293 | 'size': None, |
420 | 294 | 'min_disk': None, | ||
421 | 295 | 'min_ram': None, | ||
422 | 290 | 'location': None, | 296 | 'location': None, |
423 | 291 | 'disk_format': None, | 297 | 'disk_format': None, |
424 | 292 | 'container_format': None, | 298 | 'container_format': None, |
425 | @@ -330,6 +336,8 @@ | |||
426 | 330 | 'name': 'TestImage %d' % (i), | 336 | 'name': 'TestImage %d' % (i), |
427 | 331 | 'properties': {}, | 337 | 'properties': {}, |
428 | 332 | 'size': None, | 338 | 'size': None, |
429 | 339 | 'min_disk': None, | ||
430 | 340 | 'min_ram': None, | ||
431 | 333 | 'location': None, | 341 | 'location': None, |
432 | 334 | 'disk_format': None, | 342 | 'disk_format': None, |
433 | 335 | 'container_format': None, | 343 | 'container_format': None, |
434 | @@ -382,6 +390,8 @@ | |||
435 | 382 | 'name': 'image1', | 390 | 'name': 'image1', |
436 | 383 | 'is_public': True, | 391 | 'is_public': True, |
437 | 384 | 'size': None, | 392 | 'size': None, |
438 | 393 | 'min_disk': None, | ||
439 | 394 | 'min_ram': None, | ||
440 | 385 | 'location': None, | 395 | 'location': None, |
441 | 386 | 'disk_format': None, | 396 | 'disk_format': None, |
442 | 387 | 'container_format': None, | 397 | 'container_format': None, |
443 | @@ -416,6 +426,8 @@ | |||
444 | 416 | 'name': 'image10', | 426 | 'name': 'image10', |
445 | 417 | 'is_public': True, | 427 | 'is_public': True, |
446 | 418 | 'size': None, | 428 | 'size': None, |
447 | 429 | 'min_disk': None, | ||
448 | 430 | 'min_ram': None, | ||
449 | 419 | 'location': None, | 431 | 'location': None, |
450 | 420 | 'disk_format': None, | 432 | 'disk_format': None, |
451 | 421 | 'container_format': None, | 433 | 'container_format': None, |
452 | 422 | 434 | ||
453 | === modified file 'nova/tests/test_compute.py' | |||
454 | --- nova/tests/test_compute.py 2011-09-21 20:59:40 +0000 | |||
455 | +++ nova/tests/test_compute.py 2011-09-22 19:53:25 +0000 | |||
456 | @@ -20,6 +20,8 @@ | |||
457 | 20 | Tests For Compute | 20 | Tests For Compute |
458 | 21 | """ | 21 | """ |
459 | 22 | 22 | ||
460 | 23 | from copy import copy | ||
461 | 24 | |||
462 | 23 | from nova import compute | 25 | from nova import compute |
463 | 24 | from nova import context | 26 | from nova import context |
464 | 25 | from nova import db | 27 | from nova import db |
465 | @@ -1394,3 +1396,92 @@ | |||
466 | 1394 | self.assertEqual(self.compute_api._volume_size(inst_type, | 1396 | self.assertEqual(self.compute_api._volume_size(inst_type, |
467 | 1395 | 'swap'), | 1397 | 'swap'), |
468 | 1396 | swap_size) | 1398 | swap_size) |
469 | 1399 | |||
470 | 1400 | |||
471 | 1401 | class ComputeTestMinRamMinDisk(test.TestCase): | ||
472 | 1402 | def setUp(self): | ||
473 | 1403 | super(ComputeTestMinRamMinDisk, self).setUp() | ||
474 | 1404 | self.compute = utils.import_object(FLAGS.compute_manager) | ||
475 | 1405 | self.compute_api = compute.API() | ||
476 | 1406 | self.context = context.RequestContext('fake', 'fake') | ||
477 | 1407 | self.fake_image = { | ||
478 | 1408 | 'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1}} | ||
479 | 1409 | |||
480 | 1410 | def test_create_with_too_little_ram(self): | ||
481 | 1411 | """Test an instance type with too little memory""" | ||
482 | 1412 | |||
483 | 1413 | inst_type = instance_types.get_default_instance_type() | ||
484 | 1414 | inst_type['memory_mb'] = 1 | ||
485 | 1415 | |||
486 | 1416 | def fake_show(*args): | ||
487 | 1417 | img = copy(self.fake_image) | ||
488 | 1418 | img['min_ram'] = 2 | ||
489 | 1419 | return img | ||
490 | 1420 | self.stubs.Set(fake_image._FakeImageService, 'show', fake_show) | ||
491 | 1421 | |||
492 | 1422 | self.assertRaises(exception.InstanceTypeMemoryTooSmall, | ||
493 | 1423 | self.compute_api.create, self.context, inst_type, None) | ||
494 | 1424 | |||
495 | 1425 | # Now increase the inst_type memory and make sure all is fine. | ||
496 | 1426 | inst_type['memory_mb'] = 2 | ||
497 | 1427 | ref = self.compute_api.create(self.context, inst_type, None) | ||
498 | 1428 | self.assertTrue(ref) | ||
499 | 1429 | |||
500 | 1430 | db.instance_destroy(self.context, ref[0]['id']) | ||
501 | 1431 | |||
502 | 1432 | def test_create_with_too_little_disk(self): | ||
503 | 1433 | """Test an instance type with too little disk space""" | ||
504 | 1434 | |||
505 | 1435 | inst_type = instance_types.get_default_instance_type() | ||
506 | 1436 | inst_type['local_gb'] = 1 | ||
507 | 1437 | |||
508 | 1438 | def fake_show(*args): | ||
509 | 1439 | img = copy(self.fake_image) | ||
510 | 1440 | img['min_disk'] = 2 | ||
511 | 1441 | return img | ||
512 | 1442 | self.stubs.Set(fake_image._FakeImageService, 'show', fake_show) | ||
513 | 1443 | |||
514 | 1444 | self.assertRaises(exception.InstanceTypeDiskTooSmall, | ||
515 | 1445 | self.compute_api.create, self.context, inst_type, None) | ||
516 | 1446 | |||
517 | 1447 | # Now increase the inst_type disk space and make sure all is fine. | ||
518 | 1448 | inst_type['local_gb'] = 2 | ||
519 | 1449 | ref = self.compute_api.create(self.context, inst_type, None) | ||
520 | 1450 | self.assertTrue(ref) | ||
521 | 1451 | |||
522 | 1452 | db.instance_destroy(self.context, ref[0]['id']) | ||
523 | 1453 | |||
524 | 1454 | def test_create_just_enough_ram_and_disk(self): | ||
525 | 1455 | """Test an instance type with just enough ram and disk space""" | ||
526 | 1456 | |||
527 | 1457 | inst_type = instance_types.get_default_instance_type() | ||
528 | 1458 | inst_type['local_gb'] = 2 | ||
529 | 1459 | inst_type['memory_mb'] = 2 | ||
530 | 1460 | |||
531 | 1461 | def fake_show(*args): | ||
532 | 1462 | img = copy(self.fake_image) | ||
533 | 1463 | img['min_ram'] = 2 | ||
534 | 1464 | img['min_disk'] = 2 | ||
535 | 1465 | return img | ||
536 | 1466 | self.stubs.Set(fake_image._FakeImageService, 'show', fake_show) | ||
537 | 1467 | |||
538 | 1468 | ref = self.compute_api.create(self.context, inst_type, None) | ||
539 | 1469 | self.assertTrue(ref) | ||
540 | 1470 | |||
541 | 1471 | db.instance_destroy(self.context, ref[0]['id']) | ||
542 | 1472 | |||
543 | 1473 | def test_create_with_no_ram_and_disk_reqs(self): | ||
544 | 1474 | """Test an instance type with no min_ram or min_disk""" | ||
545 | 1475 | |||
546 | 1476 | inst_type = instance_types.get_default_instance_type() | ||
547 | 1477 | inst_type['local_gb'] = 1 | ||
548 | 1478 | inst_type['memory_mb'] = 1 | ||
549 | 1479 | |||
550 | 1480 | def fake_show(*args): | ||
551 | 1481 | return copy(self.fake_image) | ||
552 | 1482 | self.stubs.Set(fake_image._FakeImageService, 'show', fake_show) | ||
553 | 1483 | |||
554 | 1484 | ref = self.compute_api.create(self.context, inst_type, None) | ||
555 | 1485 | self.assertTrue(ref) | ||
556 | 1486 | |||
557 | 1487 | db.instance_destroy(self.context, ref[0]['id']) |
Can you change the new exception names to InstanceTypeDis kTooSmall and InstanceTypeMem oryTooSmall? I think keeping the term 'flavor' limited to the OSAPI view is a good thing to do here.
It looks like we only test passing image filters through to the image service, not that the image service actually does something with them. If you see a way we can test that, I would love to see it :) It's not a blocker for my Approve, though.