Merge lp:~rackspace-titan/nova/servers-response-formatting into lp:~hudson-openstack/nova/trunk

Proposed by Alex Meade
Status: Merged
Approved by: Brian Waldon
Approved revision: 1297
Merged at revision: 1323
Proposed branch: lp:~rackspace-titan/nova/servers-response-formatting
Merge into: lp:~hudson-openstack/nova/trunk
Diff against target: 918 lines (+658/-63)
2 files modified
nova/api/openstack/views/servers.py (+38/-7)
nova/tests/api/openstack/test_servers.py (+620/-56)
To merge this branch: bzr merge lp:~rackspace-titan/nova/servers-response-formatting
Reviewer Review Type Date Requested Status
Brian Waldon (community) Approve
Vish Ishaya (community) Approve
Review via email: mp+68119@code.launchpad.net

Description of the change

Updates /servers requests to follow the v1.1 spec. Except for implementation of uuids replacing ids and access ips both of which are not yet implemented. Also, does not include serialized xml responses.

To post a comment you must log in.
Revision history for this message
Brian Waldon (bcwaldon) wrote :

Looks good, guys. I love the view builder tests. Looking forward to the xml serialization in the next branch.

review: Approve
Revision history for this message
Vish Ishaya (vishvananda) wrote :

Nice work,

Really appreciate all of the tests going in with these branches.

review: Approve
Revision history for this message
OpenStack Infra (hudson-openstack) wrote :
Download full text (186.1 KiB)

The attempt to merge lp:~rackspace-titan/nova/servers-response-formatting into lp:nova failed. Below is the output from the failed tests.

FloatingIpTest
    test_floating_ip_allocate OK 0.31
    test_floating_ip_associate OK 0.11
    test_floating_ip_disassociate OK 0.11
    test_floating_ip_release OK 0.11
    test_floating_ip_show OK 0.13
    test_floating_ips_list OK 0.10
    test_translate_floating_ip_view OK 0.05
FixedIpTest
    test_add_fixed_ip OK 0.08
    test_add_fixed_ip_no_network OK 0.09
    test_remove_fixed_ip OK 0.29
    test_remove_fixed_ip_no_address OK 0.07
FlavorsExtraSpecsTest
    test_create OK 0.05
    test_create_empty_body OK 0.05
    test_delete OK 0.05
    test_index OK 0.05
    test_index_no_data OK 0.05
    test_show OK 0.05
    test_show_spec_not_found OK 0.05
    test_update_item OK 0.05
    test_update_item_body_uri_mismatch OK 0.05
    test_update_item_empty_body OK 0.05
    test_update_item_too_many_keys OK 0.05
AccountsTest
    test_account_create OK 0.41
    test_account_delete OK 0.18
    test_account_update OK 0.18
    test_get_account OK 0.18
AdminAPITest
    test_admin_disabled OK 0.13
    test_admin_enabled OK 0.43
APITest
    test_exceptions_are_converted_to_faults OK 0.01
    test_malformed_json OK 0.06
    test_malformed_xml OK 0.06
Test
    test_authorize_project OK 0.10
    test_authorize_token OK 0.11
    test_authorize_user OK 0.06
    test_bad_project OK 0.36
    test_bad_token OK 0.07
    test_bad_user_bad_key OK 0.06
    test_bad_user_good_key OK 0.06
    test_no_user OK 0.06
    test_not_existing_project OK 0.10
    test_token_expiry ...

Revision history for this message
Brian Waldon (bcwaldon) wrote :

Trying again.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'nova/api/openstack/views/servers.py'
2--- nova/api/openstack/views/servers.py 2011-07-21 18:21:27 +0000
3+++ nova/api/openstack/views/servers.py 2011-07-26 13:49:41 +0000
4@@ -50,7 +50,7 @@
5 else:
6 server = self._build_simple(inst)
7
8- self._build_extra(server, inst)
9+ self._build_extra(server['server'], inst)
10
11 return server
12
13@@ -99,7 +99,6 @@
14 self._build_flavor(inst_dict, inst)
15 self._build_addresses(inst_dict, inst)
16
17- inst_dict['uuid'] = inst['uuid']
18 return dict(server=inst_dict)
19
20 def _build_addresses(self, response, inst):
21@@ -121,6 +120,9 @@
22 class ViewBuilderV10(ViewBuilder):
23 """Model an Openstack API V1.0 server response."""
24
25+ def _build_extra(self, response, inst):
26+ response['uuid'] = inst['uuid']
27+
28 def _build_image(self, response, inst):
29 if 'image_ref' in dict(inst):
30 image_ref = inst['image_ref']
31@@ -145,18 +147,46 @@
32 self.image_builder = image_builder
33 self.base_url = base_url
34
35+ def _build_detail(self, inst):
36+ response = super(ViewBuilderV11, self)._build_detail(inst)
37+ response['server']['created'] = inst['created_at']
38+ response['server']['updated'] = inst['updated_at']
39+ if 'status' in response['server']:
40+ if response['server']['status'] == "ACTIVE":
41+ response['server']['progress'] = 100
42+ elif response['server']['status'] == "BUILD":
43+ response['server']['progress'] = 0
44+ return response
45+
46 def _build_image(self, response, inst):
47 if 'image_ref' in dict(inst):
48 image_href = inst['image_ref']
49- if str(image_href).isdigit():
50- image_href = int(image_href)
51- response['imageRef'] = image_href
52+ image_id = str(common.get_id_from_href(image_href))
53+ _bookmark = self.image_builder.generate_bookmark(image_id)
54+ response['image'] = {
55+ "id": image_id,
56+ "links": [
57+ {
58+ "rel": "bookmark",
59+ "href": _bookmark,
60+ },
61+ ]
62+ }
63
64 def _build_flavor(self, response, inst):
65 if "instance_type" in dict(inst):
66 flavor_id = inst["instance_type"]['flavorid']
67 flavor_ref = self.flavor_builder.generate_href(flavor_id)
68- response["flavorRef"] = flavor_ref
69+ flavor_bookmark = self.flavor_builder.generate_bookmark(flavor_id)
70+ response["flavor"] = {
71+ "id": str(common.get_id_from_href(flavor_ref)),
72+ "links": [
73+ {
74+ "rel": "bookmark",
75+ "href": flavor_bookmark,
76+ },
77+ ]
78+ }
79
80 def _build_addresses(self, response, inst):
81 interfaces = inst.get('virtual_interfaces', [])
82@@ -164,6 +194,7 @@
83
84 def _build_extra(self, response, inst):
85 self._build_links(response, inst)
86+ response['uuid'] = inst['uuid']
87
88 def _build_links(self, response, inst):
89 href = self.generate_href(inst["id"])
90@@ -180,7 +211,7 @@
91 },
92 ]
93
94- response["server"]["links"] = links
95+ response["links"] = links
96
97 def generate_href(self, server_id):
98 """Create an url that refers to a specific server id."""
99
100=== modified file 'nova/tests/api/openstack/test_servers.py'
101--- nova/tests/api/openstack/test_servers.py 2011-07-25 23:38:07 +0000
102+++ nova/tests/api/openstack/test_servers.py 2011-07-26 13:49:41 +0000
103@@ -78,6 +78,12 @@
104 return _return_virtual_interface_by_instance
105
106
107+def return_server_with_attributes(**kwargs):
108+ def _return_server(context, id):
109+ return stub_instance(id, **kwargs)
110+ return _return_server
111+
112+
113 def return_server_with_addresses(private, public):
114 def _return_server(context, id):
115 return stub_instance(id, private_address=private,
116@@ -85,12 +91,6 @@
117 return _return_server
118
119
120-def return_server_with_interfaces(interfaces):
121- def _return_server(context, id):
122- return stub_instance(id, interfaces=interfaces)
123- return _return_server
124-
125-
126 def return_server_with_power_state(power_state):
127 def _return_server(context, id):
128 return stub_instance(id, power_state=power_state)
129@@ -143,14 +143,15 @@
130
131 def stub_instance(id, user_id=1, private_address=None, public_addresses=None,
132 host=None, power_state=0, reservation_id="",
133- uuid=FAKE_UUID, interfaces=None):
134+ uuid=FAKE_UUID, image_ref="10", flavor_id="1",
135+ interfaces=None):
136 metadata = []
137 metadata.append(InstanceMetadata(key='seq', value=id))
138
139 if interfaces is None:
140 interfaces = []
141
142- inst_type = instance_types.get_instance_type_by_flavor_id(1)
143+ inst_type = instance_types.get_instance_type_by_flavor_id(int(flavor_id))
144
145 if public_addresses is None:
146 public_addresses = list()
147@@ -165,10 +166,12 @@
148
149 instance = {
150 "id": int(id),
151+ "created_at": "2010-10-10T12:00:00Z",
152+ "updated_at": "2010-11-11T11:00:00Z",
153 "admin_pass": "",
154 "user_id": user_id,
155 "project_id": "",
156- "image_ref": "10",
157+ "image_ref": image_ref,
158 "kernel_id": "",
159 "ramdisk_id": "",
160 "launch_index": 0,
161@@ -224,6 +227,7 @@
162 class ServersTest(test.TestCase):
163
164 def setUp(self):
165+ self.maxDiff = None
166 super(ServersTest, self).setUp()
167 self.stubs = stubout.StubOutForTesting()
168 fakes.FakeAuthManager.reset_fake_data()
169@@ -300,24 +304,274 @@
170 self.assertEqual(res_dict['server']['name'], 'server1')
171
172 def test_get_server_by_id_v1_1(self):
173- req = webob.Request.blank('/v1.1/servers/1')
174- res = req.get_response(fakes.wsgi_app())
175- res_dict = json.loads(res.body)
176- self.assertEqual(res_dict['server']['id'], 1)
177- self.assertEqual(res_dict['server']['name'], 'server1')
178-
179- expected_links = [
180- {
181- "rel": "self",
182- "href": "http://localhost/v1.1/servers/1",
183- },
184- {
185- "rel": "bookmark",
186- "href": "http://localhost/servers/1",
187- },
188- ]
189-
190- self.assertEqual(res_dict['server']['links'], expected_links)
191+ image_bookmark = "http://localhost/images/10"
192+ flavor_ref = "http://localhost/v1.1/flavors/1"
193+ flavor_id = "1"
194+ flavor_bookmark = "http://localhost/flavors/1"
195+
196+ public_ip = '192.168.0.3'
197+ private_ip = '172.19.0.1'
198+ interfaces = [
199+ {
200+ 'network': {'label': 'public'},
201+ 'fixed_ips': [
202+ {'address': public_ip},
203+ ],
204+ },
205+ {
206+ 'network': {'label': 'private'},
207+ 'fixed_ips': [
208+ {'address': private_ip},
209+ ],
210+ },
211+ ]
212+ new_return_server = return_server_with_attributes(
213+ interfaces=interfaces)
214+ self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
215+
216+ req = webob.Request.blank('/v1.1/servers/1')
217+ res = req.get_response(fakes.wsgi_app())
218+ res_dict = json.loads(res.body)
219+ expected_server = {
220+ "server": {
221+ "id": 1,
222+ "uuid": FAKE_UUID,
223+ "updated": "2010-11-11T11:00:00Z",
224+ "created": "2010-10-10T12:00:00Z",
225+ "progress": 0,
226+ "name": "server1",
227+ "status": "BUILD",
228+ "hostId": '',
229+ "image": {
230+ "id": "10",
231+ "links": [
232+ {
233+ "rel": "bookmark",
234+ "href": image_bookmark,
235+ },
236+ ],
237+ },
238+ "flavor": {
239+ "id": "1",
240+ "links": [
241+ {
242+ "rel": "bookmark",
243+ "href": flavor_bookmark,
244+ },
245+ ],
246+ },
247+ "addresses": {
248+ "public": [
249+ {
250+ "version": 4,
251+ "addr": public_ip,
252+ },
253+ ],
254+ "private": [
255+ {
256+ "version": 4,
257+ "addr": private_ip,
258+ },
259+ ],
260+ },
261+ "metadata": {
262+ "seq": "1",
263+ },
264+ "links": [
265+ {
266+ "rel": "self",
267+ #FIXME(wwolf) Do we want the links to be id or uuid?
268+ "href": "http://localhost/v1.1/servers/1",
269+ },
270+ {
271+ "rel": "bookmark",
272+ "href": "http://localhost/servers/1",
273+ },
274+ ],
275+ }
276+ }
277+
278+ self.assertDictMatch(res_dict, expected_server)
279+
280+ def test_get_server_with_active_status_by_id_v1_1(self):
281+ image_bookmark = "http://localhost/images/10"
282+ flavor_ref = "http://localhost/v1.1/flavors/1"
283+ flavor_id = "1"
284+ flavor_bookmark = "http://localhost/flavors/1"
285+ private_ip = "192.168.0.3"
286+ public_ip = "1.2.3.4"
287+
288+ interfaces = [
289+ {
290+ 'network': {'label': 'public'},
291+ 'fixed_ips': [
292+ {'address': public_ip},
293+ ],
294+ },
295+ {
296+ 'network': {'label': 'private'},
297+ 'fixed_ips': [
298+ {'address': private_ip},
299+ ],
300+ },
301+ ]
302+ new_return_server = return_server_with_attributes(
303+ interfaces=interfaces, power_state=1)
304+ self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
305+
306+ req = webob.Request.blank('/v1.1/servers/1')
307+ res = req.get_response(fakes.wsgi_app())
308+ res_dict = json.loads(res.body)
309+ expected_server = {
310+ "server": {
311+ "id": 1,
312+ "uuid": FAKE_UUID,
313+ "updated": "2010-11-11T11:00:00Z",
314+ "created": "2010-10-10T12:00:00Z",
315+ "progress": 100,
316+ "name": "server1",
317+ "status": "ACTIVE",
318+ "hostId": '',
319+ "image": {
320+ "id": "10",
321+ "links": [
322+ {
323+ "rel": "bookmark",
324+ "href": image_bookmark,
325+ },
326+ ],
327+ },
328+ "flavor": {
329+ "id": "1",
330+ "links": [
331+ {
332+ "rel": "bookmark",
333+ "href": flavor_bookmark,
334+ },
335+ ],
336+ },
337+ "addresses": {
338+ "public": [
339+ {
340+ "version": 4,
341+ "addr": public_ip,
342+ },
343+ ],
344+ "private": [
345+ {
346+ "version": 4,
347+ "addr": private_ip,
348+ },
349+ ],
350+ },
351+ "metadata": {
352+ "seq": "1",
353+ },
354+ "links": [
355+ {
356+ "rel": "self",
357+ "href": "http://localhost/v1.1/servers/1",
358+ },
359+ {
360+ "rel": "bookmark",
361+ "href": "http://localhost/servers/1",
362+ },
363+ ],
364+ }
365+ }
366+
367+ self.assertDictMatch(res_dict, expected_server)
368+
369+ def test_get_server_with_id_image_ref_by_id_v1_1(self):
370+ image_ref = "10"
371+ image_bookmark = "http://localhost/images/10"
372+ flavor_ref = "http://localhost/v1.1/flavors/1"
373+ flavor_id = "1"
374+ flavor_bookmark = "http://localhost/flavors/1"
375+ private_ip = "192.168.0.3"
376+ public_ip = "1.2.3.4"
377+
378+ interfaces = [
379+ {
380+ 'network': {'label': 'public'},
381+ 'fixed_ips': [
382+ {'address': public_ip},
383+ ],
384+ },
385+ {
386+ 'network': {'label': 'private'},
387+ 'fixed_ips': [
388+ {'address': private_ip},
389+ ],
390+ },
391+ ]
392+ new_return_server = return_server_with_attributes(
393+ interfaces=interfaces, power_state=1, image_ref=image_ref,
394+ flavor_id=flavor_id)
395+ self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
396+
397+ req = webob.Request.blank('/v1.1/servers/1')
398+ res = req.get_response(fakes.wsgi_app())
399+ res_dict = json.loads(res.body)
400+ expected_server = {
401+ "server": {
402+ "id": 1,
403+ "uuid": FAKE_UUID,
404+ "updated": "2010-11-11T11:00:00Z",
405+ "created": "2010-10-10T12:00:00Z",
406+ "progress": 100,
407+ "name": "server1",
408+ "status": "ACTIVE",
409+ "hostId": '',
410+ "image": {
411+ "id": "10",
412+ "links": [
413+ {
414+ "rel": "bookmark",
415+ "href": image_bookmark,
416+ },
417+ ],
418+ },
419+ "flavor": {
420+ "id": "1",
421+ "links": [
422+ {
423+ "rel": "bookmark",
424+ "href": flavor_bookmark,
425+ },
426+ ],
427+ },
428+ "addresses": {
429+ "public": [
430+ {
431+ "version": 4,
432+ "addr": public_ip,
433+ },
434+ ],
435+ "private": [
436+ {
437+ "version": 4,
438+ "addr": private_ip,
439+ },
440+ ],
441+ },
442+ "metadata": {
443+ "seq": "1",
444+ },
445+ "links": [
446+ {
447+ "rel": "self",
448+ "href": "http://localhost/v1.1/servers/1",
449+ },
450+ {
451+ "rel": "bookmark",
452+ "href": "http://localhost/servers/1",
453+ },
454+ ],
455+ }
456+ }
457+
458+ self.assertDictMatch(res_dict, expected_server)
459
460 def test_get_server_by_id_with_addresses_xml(self):
461 private = "192.168.0.3"
462@@ -452,7 +706,8 @@
463 'fixed_ipv6': '2001:4860::12',
464 },
465 ]
466- new_return_server = return_server_with_interfaces(interfaces)
467+ new_return_server = return_server_with_attributes(
468+ interfaces=interfaces)
469 self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
470
471 req = webob.Request.blank('/v1.1/servers/1')
472@@ -495,7 +750,8 @@
473 'fixed_ipv6': '2001:4860::12',
474 },
475 ]
476- new_return_server = return_server_with_interfaces(interfaces)
477+ new_return_server = return_server_with_attributes(
478+ interfaces=interfaces)
479 self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
480
481 req = webob.Request.blank('/v1.1/servers/1')
482@@ -703,20 +959,20 @@
483 for i, s in enumerate(res_dict['servers']):
484 self.assertEqual(s['id'], i)
485 self.assertEqual(s['name'], 'server%d' % i)
486- self.assertEqual(s.get('imageId', None), None)
487+ self.assertEqual(s.get('image', None), None)
488
489 expected_links = [
490- {
491- "rel": "self",
492- "href": "http://localhost/v1.1/servers/%d" % (i,),
493- },
494- {
495- "rel": "bookmark",
496- "href": "http://localhost/servers/%d" % (i,),
497- },
498- ]
499+ {
500+ "rel": "self",
501+ "href": "http://localhost/v1.1/servers/%s" % s['id'],
502+ },
503+ {
504+ "rel": "bookmark",
505+ "href": "http://localhost/servers/%s" % s['id'],
506+ },
507+ ]
508
509- self.assertEqual(s['links'], expected_links)
510+ self.assertEqual(s['links'], expected_links)
511
512 def test_get_servers_with_limit(self):
513 req = webob.Request.blank('/v1.0/servers?limit=3')
514@@ -762,13 +1018,13 @@
515 req = webob.Request.blank('/v1.1/servers?marker=2')
516 res = req.get_response(fakes.wsgi_app())
517 servers = json.loads(res.body)['servers']
518- self.assertEqual([s['id'] for s in servers], [3, 4])
519+ self.assertEqual([s['name'] for s in servers], ["server3", "server4"])
520
521 def test_get_servers_with_limit_and_marker(self):
522 req = webob.Request.blank('/v1.1/servers?limit=2&marker=1')
523 res = req.get_response(fakes.wsgi_app())
524 servers = json.loads(res.body)['servers']
525- self.assertEqual([s['id'] for s in servers], [2, 3])
526+ self.assertEqual([s['name'] for s in servers], ['server2', 'server3'])
527
528 def test_get_servers_with_bad_marker(self):
529 req = webob.Request.blank('/v1.1/servers?limit=2&marker=asdf')
530@@ -779,8 +1035,16 @@
531 def _setup_for_create_instance(self):
532 """Shared implementation for tests below that create instance"""
533 def instance_create(context, inst):
534- return {'id': 1, 'display_name': 'server_test',
535- 'uuid': FAKE_UUID}
536+ inst_type = instance_types.get_instance_type_by_flavor_id(3)
537+ image_ref = 'http://localhost/images/2'
538+ return {'id': 1,
539+ 'display_name': 'server_test',
540+ 'uuid': FAKE_UUID,
541+ 'instance_type': dict(inst_type),
542+ 'image_ref': image_ref,
543+ 'created_at': '2010-10-10T12:00:00Z',
544+ 'updated_at': '2010-11-11T11:00:00Z',
545+ }
546
547 def server_update(context, id, params):
548 return instance_create(context, id)
549@@ -980,8 +1244,26 @@
550 def test_create_instance_v1_1(self):
551 self._setup_for_create_instance()
552
553- image_href = 'http://localhost/v1.1/images/2'
554- flavor_ref = 'http://localhost/v1.1/flavors/3'
555+ image_href = 'http://localhost/images/2'
556+ flavor_ref = 'http://localhost/flavors/3'
557+ expected_flavor = {
558+ "id": "3",
559+ "links": [
560+ {
561+ "rel": "bookmark",
562+ "href": 'http://localhost/flavors/3',
563+ },
564+ ],
565+ }
566+ expected_image = {
567+ "id": "2",
568+ "links": [
569+ {
570+ "rel": "bookmark",
571+ "href": 'http://localhost/images/2',
572+ },
573+ ],
574+ }
575 body = {
576 'server': {
577 'name': 'server_test',
578@@ -1006,9 +1288,10 @@
579 server = json.loads(res.body)['server']
580 self.assertEqual(16, len(server['adminPass']))
581 self.assertEqual('server_test', server['name'])
582- self.assertEqual(1, server['id'])
583- self.assertEqual(flavor_ref, server['flavorRef'])
584- self.assertEqual(image_href, server['imageRef'])
585+ self.assertEqual(expected_flavor, server['flavor'])
586+ self.assertEqual(expected_image, server['image'])
587+ self.assertEqual(res.status_int, 200)
588+ #self.assertEqual(1, server['id'])
589
590 def test_create_instance_v1_1_invalid_flavor_href(self):
591 self._setup_for_create_instance()
592@@ -1061,8 +1344,26 @@
593 def test_create_instance_v1_1_local_href(self):
594 self._setup_for_create_instance()
595
596- image_id = 2
597- flavor_ref = 'http://localhost/v1.1/flavors/3'
598+ image_id = "2"
599+ flavor_ref = 'http://localhost/flavors/3'
600+ expected_flavor = {
601+ "id": "3",
602+ "links": [
603+ {
604+ "rel": "bookmark",
605+ "href": 'http://localhost/flavors/3',
606+ },
607+ ],
608+ }
609+ expected_image = {
610+ "id": "2",
611+ "links": [
612+ {
613+ "rel": "bookmark",
614+ "href": 'http://localhost/images/2',
615+ },
616+ ],
617+ }
618 body = {
619 'server': {
620 'name': 'server_test',
621@@ -1079,9 +1380,8 @@
622 res = req.get_response(fakes.wsgi_app())
623
624 server = json.loads(res.body)['server']
625- self.assertEqual(1, server['id'])
626- self.assertEqual(flavor_ref, server['flavorRef'])
627- self.assertEqual(image_id, server['imageRef'])
628+ self.assertEqual(expected_flavor, server['flavor'])
629+ self.assertEqual(expected_image, server['image'])
630 self.assertEqual(res.status_int, 200)
631
632 def test_create_instance_with_admin_pass_v1_0(self):
633@@ -1306,6 +1606,24 @@
634 self.assertEqual(s['metadata']['seq'], str(i))
635
636 def test_get_all_server_details_v1_1(self):
637+ expected_flavor = {
638+ "id": "1",
639+ "links": [
640+ {
641+ "rel": "bookmark",
642+ "href": 'http://localhost/flavors/1',
643+ },
644+ ],
645+ }
646+ expected_image = {
647+ "id": "10",
648+ "links": [
649+ {
650+ "rel": "bookmark",
651+ "href": 'http://localhost/images/10',
652+ },
653+ ],
654+ }
655 req = webob.Request.blank('/v1.1/servers/detail')
656 res = req.get_response(fakes.wsgi_app())
657 res_dict = json.loads(res.body)
658@@ -1314,8 +1632,8 @@
659 self.assertEqual(s['id'], i)
660 self.assertEqual(s['hostId'], '')
661 self.assertEqual(s['name'], 'server%d' % i)
662- self.assertEqual(s['imageRef'], 10)
663- self.assertEqual(s['flavorRef'], 'http://localhost/v1.1/flavors/1')
664+ self.assertEqual(s['image'], expected_image)
665+ self.assertEqual(s['flavor'], expected_flavor)
666 self.assertEqual(s['status'], 'BUILD')
667 self.assertEqual(s['metadata']['seq'], str(i))
668
669@@ -2559,3 +2877,249 @@
670 kernel_id, ramdisk_id = create_instance_helper.CreateInstanceHelper. \
671 _do_get_kernel_ramdisk_from_image(image_meta)
672 return kernel_id, ramdisk_id
673+
674+
675+class ServersViewBuilderV11Test(test.TestCase):
676+
677+ def setUp(self):
678+ self.instance = self._get_instance()
679+ self.view_builder = self._get_view_builder()
680+
681+ def tearDown(self):
682+ pass
683+
684+ def _get_instance(self):
685+ instance = {
686+ "id": 1,
687+ "created_at": "2010-10-10T12:00:00Z",
688+ "updated_at": "2010-11-11T11:00:00Z",
689+ "admin_pass": "",
690+ "user_id": "",
691+ "project_id": "",
692+ "image_ref": "5",
693+ "kernel_id": "",
694+ "ramdisk_id": "",
695+ "launch_index": 0,
696+ "key_name": "",
697+ "key_data": "",
698+ "state": 0,
699+ "state_description": "",
700+ "memory_mb": 0,
701+ "vcpus": 0,
702+ "local_gb": 0,
703+ "hostname": "",
704+ "host": "",
705+ "instance_type": {
706+ "flavorid": 1,
707+ },
708+ "user_data": "",
709+ "reservation_id": "",
710+ "mac_address": "",
711+ "scheduled_at": utils.utcnow(),
712+ "launched_at": utils.utcnow(),
713+ "terminated_at": utils.utcnow(),
714+ "availability_zone": "",
715+ "display_name": "test_server",
716+ "display_description": "",
717+ "locked": False,
718+ "metadata": [],
719+ #"address": ,
720+ #"floating_ips": [{"address":ip} for ip in public_addresses]}
721+ "uuid": "deadbeef-feed-edee-beef-d0ea7beefedd"}
722+
723+ return instance
724+
725+ def _get_view_builder(self):
726+ base_url = "http://localhost/v1.1"
727+ views = nova.api.openstack.views
728+ address_builder = views.addresses.ViewBuilderV11()
729+ flavor_builder = views.flavors.ViewBuilderV11(base_url)
730+ image_builder = views.images.ViewBuilderV11(base_url)
731+
732+ view_builder = nova.api.openstack.views.servers.ViewBuilderV11(
733+ address_builder,
734+ flavor_builder,
735+ image_builder,
736+ base_url
737+ )
738+ return view_builder
739+
740+ def test_build_server(self):
741+ expected_server = {
742+ "server": {
743+ "id": 1,
744+ "uuid": self.instance['uuid'],
745+ "name": "test_server",
746+ "links": [
747+ {
748+ "rel": "self",
749+ "href": "http://localhost/v1.1/servers/1",
750+ },
751+ {
752+ "rel": "bookmark",
753+ "href": "http://localhost/servers/1",
754+ },
755+ ],
756+ }
757+ }
758+
759+ output = self.view_builder.build(self.instance, False)
760+ self.assertDictMatch(output, expected_server)
761+
762+ def test_build_server_detail(self):
763+ image_bookmark = "http://localhost/images/5"
764+ flavor_bookmark = "http://localhost/flavors/1"
765+ expected_server = {
766+ "server": {
767+ "id": 1,
768+ "uuid": self.instance['uuid'],
769+ "updated": "2010-11-11T11:00:00Z",
770+ "created": "2010-10-10T12:00:00Z",
771+ "progress": 0,
772+ "name": "test_server",
773+ "status": "BUILD",
774+ "hostId": '',
775+ "image": {
776+ "id": "5",
777+ "links": [
778+ {
779+ "rel": "bookmark",
780+ "href": image_bookmark,
781+ },
782+ ],
783+ },
784+ "flavor": {
785+ "id": "1",
786+ "links": [
787+ {
788+ "rel": "bookmark",
789+ "href": flavor_bookmark,
790+ },
791+ ],
792+ },
793+ "addresses": {},
794+ "metadata": {},
795+ "links": [
796+ {
797+ "rel": "self",
798+ "href": "http://localhost/v1.1/servers/1",
799+ },
800+ {
801+ "rel": "bookmark",
802+ "href": "http://localhost/servers/1",
803+ },
804+ ],
805+ }
806+ }
807+
808+ output = self.view_builder.build(self.instance, True)
809+ self.assertDictMatch(output, expected_server)
810+
811+ def test_build_server_detail_active_status(self):
812+ #set the power state of the instance to running
813+ self.instance['state'] = 1
814+ image_bookmark = "http://localhost/images/5"
815+ flavor_bookmark = "http://localhost/flavors/1"
816+ expected_server = {
817+ "server": {
818+ "id": 1,
819+ "uuid": self.instance['uuid'],
820+ "updated": "2010-11-11T11:00:00Z",
821+ "created": "2010-10-10T12:00:00Z",
822+ "progress": 100,
823+ "name": "test_server",
824+ "status": "ACTIVE",
825+ "hostId": '',
826+ "image": {
827+ "id": "5",
828+ "links": [
829+ {
830+ "rel": "bookmark",
831+ "href": image_bookmark,
832+ },
833+ ],
834+ },
835+ "flavor": {
836+ "id": "1",
837+ "links": [
838+ {
839+ "rel": "bookmark",
840+ "href": flavor_bookmark,
841+ },
842+ ],
843+ },
844+ "addresses": {},
845+ "metadata": {},
846+ "links": [
847+ {
848+ "rel": "self",
849+ "href": "http://localhost/v1.1/servers/1",
850+ },
851+ {
852+ "rel": "bookmark",
853+ "href": "http://localhost/servers/1",
854+ },
855+ ],
856+ }
857+ }
858+
859+ output = self.view_builder.build(self.instance, True)
860+ self.assertDictMatch(output, expected_server)
861+
862+ def test_build_server_detail_with_metadata(self):
863+
864+ metadata = []
865+ metadata.append(InstanceMetadata(key="Open", value="Stack"))
866+ metadata.append(InstanceMetadata(key="Number", value=1))
867+ self.instance['metadata'] = metadata
868+
869+ image_bookmark = "http://localhost/images/5"
870+ flavor_bookmark = "http://localhost/flavors/1"
871+ expected_server = {
872+ "server": {
873+ "id": 1,
874+ "uuid": self.instance['uuid'],
875+ "updated": "2010-11-11T11:00:00Z",
876+ "created": "2010-10-10T12:00:00Z",
877+ "progress": 0,
878+ "name": "test_server",
879+ "status": "BUILD",
880+ "hostId": '',
881+ "image": {
882+ "id": "5",
883+ "links": [
884+ {
885+ "rel": "bookmark",
886+ "href": image_bookmark,
887+ },
888+ ],
889+ },
890+ "flavor": {
891+ "id": "1",
892+ "links": [
893+ {
894+ "rel": "bookmark",
895+ "href": flavor_bookmark,
896+ },
897+ ],
898+ },
899+ "addresses": {},
900+ "metadata": {
901+ "Open": "Stack",
902+ "Number": "1",
903+ },
904+ "links": [
905+ {
906+ "rel": "self",
907+ "href": "http://localhost/v1.1/servers/1",
908+ },
909+ {
910+ "rel": "bookmark",
911+ "href": "http://localhost/servers/1",
912+ },
913+ ],
914+ }
915+ }
916+
917+ output = self.view_builder.build(self.instance, True)
918+ self.assertDictMatch(output, expected_server)