Merge lp:~rackspace-titan/nova/password-on-server-create into lp:~hudson-openstack/nova/trunk

Proposed by Mark Washenberger
Status: Merged
Approved by: Jay Pipes
Approved revision: 952
Merged at revision: 998
Proposed branch: lp:~rackspace-titan/nova/password-on-server-create
Merge into: lp:~hudson-openstack/nova/trunk
Diff against target: 123 lines (+80/-1)
2 files modified
nova/api/openstack/servers.py (+16/-1)
nova/tests/api/openstack/test_servers.py (+64/-0)
To merge this branch: bzr merge lp:~rackspace-titan/nova/password-on-server-create
Reviewer Review Type Date Requested Status
Jay Pipes (community) Approve
Rick Harris (community) Approve
Brian Waldon (community) Approve
Review via email: mp+56461@code.launchpad.net

Description of the change

Support admin password when specified in server create requests.

To post a comment you must log in.
Revision history for this message
Jay Pipes (jaypipes) wrote :

lgtm. nice work.

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

A docstring that makes it clear what _get_server_admin_password does would make me feel better. If someone came to the module and saw that function name, they may think it would retrieve the adminPass from the actual instance, while it might actually generate something random.

review: Needs Fixing
Revision history for this message
Mark Washenberger (markwash) wrote :

I hope these docstrings fit the bill.

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

Sorry for being such a quibbler!

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

If I'm reading the logic correctly, it looks like you need one more test case for complete coverage:

def test_create_instance_without_admin_pass_v11(self):
    """Ensure that V11 will generate a random password if adminPass isn't passed in with request"""

...code above...

body = {
    'server': {
        'name': 'server_test',
        'imageRef': imageRef,
        'flavorRef': flavorRef,
    },
}

...code below...

review: Needs Fixing
Revision history for this message
Mark Washenberger (markwash) wrote :

While I'd almost never object to more coverage, I think this case is covered by the test_create_instance_v11 testcase.

Thanks!

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

You're right, I should have poked around the file a bit more.

Thanks.

review: Approve
Revision history for this message
OpenStack Infra (hudson-openstack) wrote :

Attempt to merge into lp:nova failed due to conflicts:

text conflict in nova/api/openstack/servers.py

Revision history for this message
Mark Washenberger (markwash) wrote :

Fixed merge conflicts. Sorry.

Revision history for this message
Jay Pipes (jaypipes) :
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/servers.py'
2--- nova/api/openstack/servers.py 2011-04-08 00:32:34 +0000
3+++ nova/api/openstack/servers.py 2011-04-18 21:46:11 +0000
4@@ -118,6 +118,8 @@
5
6 context = req.environ['nova.context']
7
8+ password = self._get_server_admin_password(env['server'])
9+
10 key_name = None
11 key_data = None
12 key_pairs = auth_manager.AuthManager.get_key_pairs(context)
13@@ -180,7 +182,6 @@
14
15 builder = self._get_view_builder(req)
16 server = builder.build(inst, is_detail=True)
17- password = utils.generate_password(16)
18 server['server']['adminPass'] = password
19 self.compute_api.set_admin_password(context, server['server']['id'],
20 password)
21@@ -242,6 +243,10 @@
22 # if the original error is okay, just reraise it
23 raise error
24
25+ def _get_server_admin_password(self, server):
26+ """ Determine the admin password for a server on creation """
27+ return utils.generate_password(16)
28+
29 @scheduler_api.redirect_handler
30 def update(self, req, id):
31 """ Updates the server name or password """
32@@ -648,6 +653,16 @@
33 def _limit_items(self, items, req):
34 return common.limited_by_marker(items, req)
35
36+ def _get_server_admin_password(self, server):
37+ """ Determine the admin password for a server on creation """
38+ password = server.get('adminPass')
39+ if password is None:
40+ return utils.generate_password(16)
41+ if not isinstance(password, basestring) or password == '':
42+ msg = _("Invalid adminPass")
43+ raise exc.HTTPBadRequest(msg)
44+ return password
45+
46 def get_default_xmlns(self, req):
47 return common.XML_NS_V11
48
49
50=== modified file 'nova/tests/api/openstack/test_servers.py'
51--- nova/tests/api/openstack/test_servers.py 2011-04-18 20:40:16 +0000
52+++ nova/tests/api/openstack/test_servers.py 2011-04-18 21:46:11 +0000
53@@ -613,6 +613,70 @@
54 res = req.get_response(fakes.wsgi_app())
55 self.assertEqual(res.status_int, 400)
56
57+ def test_create_instance_with_admin_pass_v10(self):
58+ self._setup_for_create_instance()
59+
60+ body = {
61+ 'server': {
62+ 'name': 'test-server-create',
63+ 'imageId': 3,
64+ 'flavorId': 1,
65+ 'adminPass': 'testpass',
66+ },
67+ }
68+
69+ req = webob.Request.blank('/v1.0/servers')
70+ req.method = 'POST'
71+ req.body = json.dumps(body)
72+ req.headers['content-type'] = "application/json"
73+ res = req.get_response(fakes.wsgi_app())
74+ res = json.loads(res.body)
75+ self.assertNotEqual(res['server']['adminPass'],
76+ body['server']['adminPass'])
77+
78+ def test_create_instance_with_admin_pass_v11(self):
79+ self._setup_for_create_instance()
80+
81+ imageRef = 'http://localhost/v1.1/images/2'
82+ flavorRef = 'http://localhost/v1.1/flavors/3'
83+ body = {
84+ 'server': {
85+ 'name': 'server_test',
86+ 'imageRef': imageRef,
87+ 'flavorRef': flavorRef,
88+ 'adminPass': 'testpass',
89+ },
90+ }
91+
92+ req = webob.Request.blank('/v1.1/servers')
93+ req.method = 'POST'
94+ req.body = json.dumps(body)
95+ req.headers['content-type'] = "application/json"
96+ res = req.get_response(fakes.wsgi_app())
97+ server = json.loads(res.body)['server']
98+ self.assertEqual(server['adminPass'], body['server']['adminPass'])
99+
100+ def test_create_instance_with_empty_admin_pass_v11(self):
101+ self._setup_for_create_instance()
102+
103+ imageRef = 'http://localhost/v1.1/images/2'
104+ flavorRef = 'http://localhost/v1.1/flavors/3'
105+ body = {
106+ 'server': {
107+ 'name': 'server_test',
108+ 'imageRef': imageRef,
109+ 'flavorRef': flavorRef,
110+ 'adminPass': '',
111+ },
112+ }
113+
114+ req = webob.Request.blank('/v1.1/servers')
115+ req.method = 'POST'
116+ req.body = json.dumps(body)
117+ req.headers['content-type'] = "application/json"
118+ res = req.get_response(fakes.wsgi_app())
119+ self.assertEqual(res.status_int, 400)
120+
121 def test_update_no_body(self):
122 req = webob.Request.blank('/v1.0/servers/1')
123 req.method = 'PUT'