Merge lp:~cerberus/nova/os-api-retune into lp:~hudson-openstack/nova/trunk

Proposed by Matt Dietz
Status: Merged
Approved by: Eric Day
Approved revision: 500
Merged at revision: 502
Proposed branch: lp:~cerberus/nova/os-api-retune
Merge into: lp:~hudson-openstack/nova/trunk
Diff against target: 219 lines (+65/-28)
5 files modified
nova/api/openstack/__init__.py (+1/-1)
nova/api/openstack/backup_schedules.py (+14/-1)
nova/api/openstack/ratelimiting/__init__.py (+2/-2)
nova/api/openstack/servers.py (+16/-17)
nova/api/openstack/sharedipgroups.py (+32/-7)
To merge this branch: bzr merge lp:~cerberus/nova/os-api-retune
Reviewer Review Type Date Requested Status
Eric Day (community) Approve
Todd Willey (community) Approve
Review via email: mp+44763@code.launchpad.net

Description of the change

Changes and error fixes to help ensure basic parity with the Rackspace API. Some features are still missing, such as shared ip groups, and will be added in a later patch set.

To post a comment you must log in.
Revision history for this message
Eric Day (eday) wrote :

So I see you renamed _entity_* to _translate_* in servers, but in other files you introduced the equivalent functions as _entity_*. It would be nice to have consistency in the naming, whichever one it is you prefer. :)

review: Needs Fixing
Revision history for this message
Matt Dietz (cerberus) wrote :

Yeah, I meant to get after that today. Thanks for the reminder :-)

Revision history for this message
Rick Harris (rconradharris) wrote :

Overall, lgtm.

> + inst_ref = self.compute_api.get_instance(ctxt, id)

This line is added in update(), but inst_ref isn't referenced later. Is this to trigger an exception as a side-effect? If that's the case, that might merit a comment.

Revision history for this message
Todd Willey (xtoddx) wrote :

lgtm

review: Approve
Revision history for this message
Matt Dietz (cerberus) wrote :

Rick: good catch. Superfluous line.

lp:~cerberus/nova/os-api-retune updated
500. By Matt Dietz

removed superfluous line

Revision history for this message
Eric Day (eday) wrote :

lgtm

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'nova/api/openstack/__init__.py'
--- nova/api/openstack/__init__.py 2010-12-23 21:33:16 +0000
+++ nova/api/openstack/__init__.py 2010-12-28 23:36:26 +0000
@@ -100,7 +100,7 @@
100 collection={'detail': 'GET'},100 collection={'detail': 'GET'},
101 member=server_members)101 member=server_members)
102102
103 mapper.resource("backup_schedule", "backup_schedules",103 mapper.resource("backup_schedule", "backup_schedule",
104 controller=backup_schedules.Controller(),104 controller=backup_schedules.Controller(),
105 parent_resource=dict(member_name='server',105 parent_resource=dict(member_name='server',
106 collection_name='servers'))106 collection_name='servers'))
107107
=== modified file 'nova/api/openstack/backup_schedules.py'
--- nova/api/openstack/backup_schedules.py 2010-12-22 20:59:53 +0000
+++ nova/api/openstack/backup_schedules.py 2010-12-28 23:36:26 +0000
@@ -23,13 +23,25 @@
23import nova.image.service23import nova.image.service
2424
2525
26def _translate_keys(inst):
27 """ Coerces the backup schedule into proper dictionary format """
28 return dict(backupSchedule=inst)
29
30
26class Controller(wsgi.Controller):31class Controller(wsgi.Controller):
32 """ The backup schedule API controller for the Openstack API """
33
34 _serialization_metadata = {
35 'application/xml': {
36 'attributes': {
37 'backupSchedule': []}}}
2738
28 def __init__(self):39 def __init__(self):
29 pass40 pass
3041
31 def index(self, req, server_id):42 def index(self, req, server_id):
32 return faults.Fault(exc.HTTPNotFound())43 """ Returns the list of backup schedules for a given instance """
44 return _translate_keys({})
3345
34 def create(self, req, server_id):46 def create(self, req, server_id):
35 """ No actual update method required, since the existing API allows47 """ No actual update method required, since the existing API allows
@@ -37,4 +49,5 @@
37 return faults.Fault(exc.HTTPNotFound())49 return faults.Fault(exc.HTTPNotFound())
3850
39 def delete(self, req, server_id, id):51 def delete(self, req, server_id, id):
52 """ Deletes an existing backup schedule """
40 return faults.Fault(exc.HTTPNotFound())53 return faults.Fault(exc.HTTPNotFound())
4154
=== modified file 'nova/api/openstack/ratelimiting/__init__.py'
--- nova/api/openstack/ratelimiting/__init__.py 2010-12-23 19:17:53 +0000
+++ nova/api/openstack/ratelimiting/__init__.py 2010-12-28 23:36:26 +0000
@@ -64,9 +64,9 @@
64 If the request should be rate limited, return a 413 status with a64 If the request should be rate limited, return a 413 status with a
65 Retry-After header giving the time when the request would succeed.65 Retry-After header giving the time when the request would succeed.
66 """66 """
67 return self.limited_request(req, self.application)67 return self.rate_limited_request(req, self.application)
6868
69 def limited_request(self, req, application):69 def rate_limited_request(self, req, application):
70 """Rate limit the request.70 """Rate limit the request.
7171
72 If the request should be rate limited, return a 413 status with a72 If the request should be rate limited, return a 413 status with a
7373
=== modified file 'nova/api/openstack/servers.py'
--- nova/api/openstack/servers.py 2010-12-23 21:33:16 +0000
+++ nova/api/openstack/servers.py 2010-12-28 23:36:26 +0000
@@ -35,14 +35,11 @@
35LOG.setLevel(logging.DEBUG)35LOG.setLevel(logging.DEBUG)
3636
3737
38def _entity_list(entities):38def _translate_detail_keys(inst):
39 """ Coerces a list of servers into proper dictionary format """39 """ Coerces into dictionary format, mapping everything to Rackspace-like
40 return dict(servers=entities)40 attributes for return"""
41
42
43def _entity_detail(inst):
44 """ Maps everything to Rackspace-like attributes for return"""
45 power_mapping = {41 power_mapping = {
42 None: 'build',
46 power_state.NOSTATE: 'build',43 power_state.NOSTATE: 'build',
47 power_state.RUNNING: 'active',44 power_state.RUNNING: 'active',
48 power_state.BLOCKED: 'active',45 power_state.BLOCKED: 'active',
@@ -67,8 +64,9 @@
67 return dict(server=inst_dict)64 return dict(server=inst_dict)
6865
6966
70def _entity_inst(inst):67def _translate_keys(inst):
71 """ Filters all model attributes save for id and name """68 """ Coerces into dictionary format, excluding all model attributes
69 save for id and name """
72 return dict(server=dict(id=inst['internal_id'], name=inst['display_name']))70 return dict(server=dict(id=inst['internal_id'], name=inst['display_name']))
7371
7472
@@ -87,29 +85,29 @@
8785
88 def index(self, req):86 def index(self, req):
89 """ Returns a list of server names and ids for a given user """87 """ Returns a list of server names and ids for a given user """
90 return self._items(req, entity_maker=_entity_inst)88 return self._items(req, entity_maker=_translate_keys)
9189
92 def detail(self, req):90 def detail(self, req):
93 """ Returns a list of server details for a given user """91 """ Returns a list of server details for a given user """
94 return self._items(req, entity_maker=_entity_detail)92 return self._items(req, entity_maker=_translate_detail_keys)
9593
96 def _items(self, req, entity_maker):94 def _items(self, req, entity_maker):
97 """Returns a list of servers for a given user.95 """Returns a list of servers for a given user.
9896
99 entity_maker - either _entity_detail or _entity_inst97 entity_maker - either _translate_detail_keys or _translate_keys
100 """98 """
101 instance_list = self.compute_api.get_instances(99 instance_list = self.compute_api.get_instances(
102 req.environ['nova.context'])100 req.environ['nova.context'])
103 limited_list = common.limited(instance_list, req)101 limited_list = common.limited(instance_list, req)
104 res = [entity_maker(inst)['server'] for inst in limited_list]102 res = [entity_maker(inst)['server'] for inst in limited_list]
105 return _entity_list(res)103 return dict(servers=res)
106104
107 def show(self, req, id):105 def show(self, req, id):
108 """ Returns server details by server id """106 """ Returns server details by server id """
109 try:107 try:
110 instance = self.compute_api.get_instance(108 instance = self.compute_api.get_instance(
111 req.environ['nova.context'], int(id))109 req.environ['nova.context'], int(id))
112 return _entity_detail(instance)110 return _translate_detail_keys(instance)
113 except exception.NotFound:111 except exception.NotFound:
114 return faults.Fault(exc.HTTPNotFound())112 return faults.Fault(exc.HTTPNotFound())
115113
@@ -138,7 +136,7 @@
138 description=env['server']['name'],136 description=env['server']['name'],
139 key_name=key_pair['name'],137 key_name=key_pair['name'],
140 key_data=key_pair['public_key'])138 key_data=key_pair['public_key'])
141 return _entity_inst(instances[0])139 return _translate_keys(instances[0])
142140
143 def update(self, req, id):141 def update(self, req, id):
144 """ Updates the server name or password """142 """ Updates the server name or password """
@@ -153,8 +151,9 @@
153 update_dict['display_name'] = inst_dict['server']['name']151 update_dict['display_name'] = inst_dict['server']['name']
154152
155 try:153 try:
156 self.compute_api.update_instance(req.environ['nova.context'],154 ctxt = req.environ['nova.context']
157 instance['id'],155 self.compute_api.update_instance(ctxt,
156 id,
158 **update_dict)157 **update_dict)
159 except exception.NotFound:158 except exception.NotFound:
160 return faults.Fault(exc.HTTPNotFound())159 return faults.Fault(exc.HTTPNotFound())
161160
=== modified file 'nova/api/openstack/sharedipgroups.py'
--- nova/api/openstack/sharedipgroups.py 2010-12-23 19:17:53 +0000
+++ nova/api/openstack/sharedipgroups.py 2010-12-28 23:36:26 +0000
@@ -15,26 +15,51 @@
15# License for the specific language governing permissions and limitations15# License for the specific language governing permissions and limitations
16# under the License.16# under the License.
1717
18from webob import exc
19
18from nova import wsgi20from nova import wsgi
21from nova.api.openstack import faults
22
23
24def _translate_keys(inst):
25 """ Coerces a shared IP group instance into proper dictionary format """
26 return dict(sharedIpGroup=inst)
27
28
29def _translate_detail_keys(inst):
30 """ Coerces a shared IP group instance into proper dictionary format with
31 correctly mapped attributes """
32 return dict(sharedIpGroup=inst)
1933
2034
21class Controller(wsgi.Controller):35class Controller(wsgi.Controller):
22 """ The Shared IP Groups Controller for the Openstack API """36 """ The Shared IP Groups Controller for the Openstack API """
2337
38 _serialization_metadata = {
39 'application/xml': {
40 'attributes': {
41 'sharedIpGroup': []}}}
42
24 def index(self, req):43 def index(self, req):
25 raise NotImplementedError44 """ Returns a list of Shared IP Groups for the user """
45 return dict(sharedIpGroups=[])
2646
27 def show(self, req, id):47 def show(self, req, id):
28 raise NotImplementedError48 """ Shows in-depth information on a specific Shared IP Group """
49 return _translate_keys({})
2950
30 def update(self, req, id):51 def update(self, req, id):
31 raise NotImplementedError52 """ You can't update a Shared IP Group """
53 raise faults.Fault(exc.HTTPNotImplemented())
3254
33 def delete(self, req, id):55 def delete(self, req, id):
34 raise NotImplementedError56 """ Deletes a Shared IP Group """
57 raise faults.Fault(exc.HTTPNotFound())
3558
36 def detail(self, req):59 def detail(self, req, id):
37 raise NotImplementedError60 """ Returns a complete list of Shared IP Groups """
61 return _translate_detail_keys({})
3862
39 def create(self, req):63 def create(self, req):
40 raise NotImplementedError64 """ Creates a new Shared IP group """
65 raise faults.Fault(exc.HTTPNotFound())