Merge lp:~jaypipes/nova/compute-manager-instance-data into lp:~hudson-openstack/nova/trunk

Proposed by Jay Pipes
Status: Merged
Approved by: Eric Day
Approved revision: 376
Merged at revision: 388
Proposed branch: lp:~jaypipes/nova/compute-manager-instance-data
Merge into: lp:~hudson-openstack/nova/trunk
Diff against target: 443 lines (+104/-78)
7 files modified
nova/api/ec2/cloud.py (+18/-16)
nova/api/openstack/servers.py (+12/-15)
nova/compute/manager.py (+40/-0)
nova/db/sqlalchemy/api.py (+22/-44)
nova/db/sqlalchemy/models.py (+10/-0)
nova/tests/api/openstack/fakes.py (+1/-0)
nova/tests/api/openstack/test_servers.py (+1/-3)
To merge this branch: bzr merge lp:~jaypipes/nova/compute-manager-instance-data
Reviewer Review Type Date Requested Status
Eric Day (community) Approve
Devin Carlen (community) Approve
Review via email: mp+39182@code.launchpad.net

Commit message

Moves db writes into compute manager class. Cleans up sqlalchemy model/api to remove redundant calls for updating what is really a dict.

Description of the change

Moves db writes into compute manager class. Cleans up sqlalchemy model/api to remove redundant calls for updating what is really a dict.

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

The second part looks fine, but any reason you build a dict and pass that for instance_data rather than just using kwargs directly for create/update_instance? For example:

self.compute_manager.create_instance(context, security_groups=security_groups, mac_address=utils.generate_mac(), launch_index=num, **base_options)

And then just use **kwargs inside the methods to pass to the DB layer?

Also, this has text conflicts with trunk and introduces pep8 violations. :)

review: Needs Fixing
Revision history for this message
Jay Pipes (jaypipes) wrote :

On Mon, Oct 25, 2010 at 7:38 PM, Eric Day <email address hidden> wrote:
> Review: Needs Fixing
> The second part looks fine, but any reason you build a dict and pass that for instance_data rather than just using kwargs directly for create/update_instance? For example:
>
> self.compute_manager.create_instance(context, security_groups=security_groups, mac_address=utils.generate_mac(), launch_index=num, **base_options)
>
> And then just use **kwargs inside the methods to pass to the DB layer?

Ya, good point :)

> Also, this has text conflicts with trunk and introduces pep8 violations. :)

I will fix em shortly.

Cheers!
jay

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

Hmm, this might be too nit picky, but this still seems a bit more verbose than it needs to be. :)

For example, lines 18-24 could just be:

instance_ref = self.compute_manager.create_instance(context, security_groups, mac_address=utils.generate_mac(), launch_index=num, **base_options)

And create_instance would be changed to:

def create_instance(self, context, security_groups=[], **kwargs):
    instance_ref = self.db.instance_create(context, kwargs)
    inst_id = instance_ref['id']
...

Also, 57-62 could be:

self.compute_manager.update_instance(context, instance_ref['id'], state_description='terminating', state=0, terminated_at=now)

And again use **kwargs directly in update_instance. I guess I just prefer passing kwargs directly rather than passing in a dict for these sorts of things.

review: Needs Fixing
Revision history for this message
Devin Carlen (devcamcar) wrote :

Good stuff! Always love to see the middle tier emerge more.

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

The 'updated_data' variable is no longer used (lines 54-56). Other than that, looks good!

review: Needs Fixing
Revision history for this message
Jay Pipes (jaypipes) wrote :

OK, removed the updated_data variable.

376. By Jay Pipes

Remove unused updated_data variable

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
1=== modified file 'nova/api/ec2/cloud.py'
2--- nova/api/ec2/cloud.py 2010-10-26 00:44:23 +0000
3+++ nova/api/ec2/cloud.py 2010-10-28 15:46:05 +0000
4@@ -99,6 +99,7 @@
5 """
6 def __init__(self):
7 self.network_manager = utils.import_object(FLAGS.network_manager)
8+ self.compute_manager = utils.import_object(FLAGS.compute_manager)
9 self.setup()
10
11 def __str__(self):
12@@ -835,21 +836,21 @@
13 elevated = context.elevated()
14
15 for num in range(num_instances):
16- instance_ref = db.instance_create(context, base_options)
17+
18+ instance_ref = self.compute_manager.create_instance(context,
19+ security_groups,
20+ mac_address=utils.generate_mac(),
21+ launch_index=num,
22+ **base_options)
23 inst_id = instance_ref['id']
24
25- for security_group_id in security_groups:
26- db.instance_add_security_group(elevated,
27- inst_id,
28- security_group_id)
29-
30- inst = {}
31- inst['mac_address'] = utils.generate_mac()
32- inst['launch_index'] = num
33 internal_id = instance_ref['internal_id']
34 ec2_id = internal_id_to_ec2_id(internal_id)
35- inst['hostname'] = ec2_id
36- db.instance_update(context, inst_id, inst)
37+
38+ self.compute_manager.update_instance(context,
39+ inst_id,
40+ hostname=ec2_id)
41+
42 # TODO(vish): This probably should be done in the scheduler
43 # or in compute as a call. The network should be
44 # allocated after the host is assigned and setup
45@@ -895,11 +896,12 @@
46 id_str)
47 continue
48 now = datetime.datetime.utcnow()
49- db.instance_update(context,
50- instance_ref['id'],
51- {'state_description': 'terminating',
52- 'state': 0,
53- 'terminated_at': now})
54+ self.compute_manager.update_instance(context,
55+ instance_ref['id'],
56+ state_description='terminating',
57+ state=0,
58+ terminated_at=now)
59+
60 # FIXME(ja): where should network deallocate occur?
61 address = db.instance_get_floating_address(context,
62 instance_ref['id'])
63
64=== modified file 'nova/api/openstack/servers.py'
65--- nova/api/openstack/servers.py 2010-10-21 22:26:06 +0000
66+++ nova/api/openstack/servers.py 2010-10-28 15:46:05 +0000
67@@ -95,6 +95,7 @@
68 db_driver = FLAGS.db_driver
69 self.db_driver = utils.import_object(db_driver)
70 self.network_manager = utils.import_object(FLAGS.network_manager)
71+ self.compute_manager = utils.import_object(FLAGS.compute_manager)
72 super(Controller, self).__init__()
73
74 def index(self, req):
75@@ -242,34 +243,30 @@
76 inst['memory_mb'] = flavor['memory_mb']
77 inst['vcpus'] = flavor['vcpus']
78 inst['local_gb'] = flavor['local_gb']
79-
80- ref = self.db_driver.instance_create(ctxt, inst)
81- inst['id'] = ref.internal_id
82-
83 inst['mac_address'] = utils.generate_mac()
84-
85- #TODO(dietz) is this necessary?
86 inst['launch_index'] = 0
87
88- inst['hostname'] = str(ref.internal_id)
89- self.db_driver.instance_update(ctxt, inst['id'], inst)
90-
91- network_manager = utils.import_object(FLAGS.network_manager)
92- address = network_manager.allocate_fixed_ip(ctxt,
93- inst['id'])
94+ ref = self.compute_manager.create_instance(ctxt, **inst)
95+ inst['id'] = ref['internal_id']
96+
97+ inst['hostname'] = str(ref['internal_id'])
98+ self.compute_manager.update_instance(ctxt, inst['id'], **inst)
99+
100+ address = self.network_manager.allocate_fixed_ip(ctxt,
101+ inst['id'])
102
103 # TODO(vish): This probably should be done in the scheduler
104 # network is setup when host is assigned
105- network_topic = self._get_network_topic(ctxt, network_manager)
106+ network_topic = self._get_network_topic(ctxt)
107 rpc.call(ctxt,
108 network_topic,
109 {"method": "setup_fixed_ip",
110 "args": {"address": address}})
111 return inst
112
113- def _get_network_topic(self, context, network_manager):
114+ def _get_network_topic(self, context):
115 """Retrieves the network host for a project"""
116- network_ref = network_manager.get_network(context)
117+ network_ref = self.network_manager.get_network(context)
118 host = network_ref['host']
119 if not host:
120 host = rpc.call(context,
121
122=== modified file 'nova/compute/manager.py'
123--- nova/compute/manager.py 2010-10-25 02:52:02 +0000
124+++ nova/compute/manager.py 2010-10-28 15:46:05 +0000
125@@ -69,6 +69,46 @@
126 def refresh_security_group(self, context, security_group_id, **_kwargs):
127 yield self.driver.refresh_security_group(security_group_id)
128
129+ def create_instance(self, context, security_groups=[], **kwargs):
130+ """Creates the instance in the datastore and returns the
131+ new instance as a mapping
132+
133+ :param context: The security context
134+ :param security_groups: list of security group ids to
135+ attach to the instance
136+ :param **kwargs: All additional keyword args are treated
137+ as data fields of the instance to be
138+ created
139+
140+ :retval Returns a mapping of the instance information
141+ that has just been created
142+
143+ """
144+ instance_ref = self.db.instance_create(context, kwargs)
145+ inst_id = instance_ref['id']
146+
147+ elevated = context.elevated()
148+ security_groups = kwargs.get('security_groups', [])
149+ for security_group_id in security_groups:
150+ self.db.instance_add_security_group(elevated,
151+ inst_id,
152+ security_group_id)
153+ return instance_ref
154+
155+ def update_instance(self, context, instance_id, **kwargs):
156+ """Updates the instance in the datastore
157+
158+ :param context: The security context
159+ :param instance_id: ID of the instance to update
160+ :param **kwargs: All additional keyword args are treated
161+ as data fields of the instance to be
162+ updated
163+
164+ :retval None
165+
166+ """
167+ self.db.instance_update(context, instance_id, kwargs)
168+
169 @defer.inlineCallbacks
170 @exception.wrap_exception
171 def run_instance(self, context, instance_id, **_kwargs):
172
173=== modified file 'nova/db/sqlalchemy/api.py'
174--- nova/db/sqlalchemy/api.py 2010-10-26 00:15:56 +0000
175+++ nova/db/sqlalchemy/api.py 2010-10-28 15:46:05 +0000
176@@ -236,8 +236,7 @@
177 @require_admin_context
178 def service_create(context, values):
179 service_ref = models.Service()
180- for (key, value) in values.iteritems():
181- service_ref[key] = value
182+ service_ref.update(values)
183 service_ref.save()
184 return service_ref
185
186@@ -247,8 +246,7 @@
187 session = get_session()
188 with session.begin():
189 service_ref = service_get(context, service_id, session=session)
190- for (key, value) in values.iteritems():
191- service_ref[key] = value
192+ service_ref.update(values)
193 service_ref.save(session=session)
194
195
196@@ -279,8 +277,7 @@
197 @require_context
198 def floating_ip_create(context, values):
199 floating_ip_ref = models.FloatingIp()
200- for (key, value) in values.iteritems():
201- floating_ip_ref[key] = value
202+ floating_ip_ref.update(values)
203 floating_ip_ref.save()
204 return floating_ip_ref['address']
205
206@@ -451,8 +448,7 @@
207 @require_context
208 def fixed_ip_create(_context, values):
209 fixed_ip_ref = models.FixedIp()
210- for (key, value) in values.iteritems():
211- fixed_ip_ref[key] = value
212+ fixed_ip_ref.update(values)
213 fixed_ip_ref.save()
214 return fixed_ip_ref['address']
215
216@@ -523,8 +519,7 @@
217 fixed_ip_ref = fixed_ip_get_by_address(context,
218 address,
219 session=session)
220- for (key, value) in values.iteritems():
221- fixed_ip_ref[key] = value
222+ fixed_ip_ref.update(values)
223 fixed_ip_ref.save(session=session)
224
225
226@@ -537,8 +532,7 @@
227 @require_context
228 def instance_create(context, values):
229 instance_ref = models.Instance()
230- for (key, value) in values.iteritems():
231- instance_ref[key] = value
232+ instance_ref.update(values)
233
234 session = get_session()
235 with session.begin():
236@@ -731,8 +725,7 @@
237 session = get_session()
238 with session.begin():
239 instance_ref = instance_get(context, instance_id, session=session)
240- for (key, value) in values.iteritems():
241- instance_ref[key] = value
242+ instance_ref.update(values)
243 instance_ref.save(session=session)
244
245
246@@ -754,8 +747,7 @@
247 @require_context
248 def key_pair_create(context, values):
249 key_pair_ref = models.KeyPair()
250- for (key, value) in values.iteritems():
251- key_pair_ref[key] = value
252+ key_pair_ref.update(values)
253 key_pair_ref.save()
254 return key_pair_ref
255
256@@ -870,8 +862,7 @@
257 @require_admin_context
258 def network_create_safe(context, values):
259 network_ref = models.Network()
260- for (key, value) in values.iteritems():
261- network_ref[key] = value
262+ network_ref.update(values)
263 try:
264 network_ref.save()
265 return network_ref
266@@ -980,8 +971,7 @@
267 session = get_session()
268 with session.begin():
269 network_ref = network_get(context, network_id, session=session)
270- for (key, value) in values.iteritems():
271- network_ref[key] = value
272+ network_ref.update(values)
273 network_ref.save(session=session)
274
275
276@@ -1031,8 +1021,7 @@
277 @require_admin_context
278 def export_device_create_safe(context, values):
279 export_device_ref = models.ExportDevice()
280- for (key, value) in values.iteritems():
281- export_device_ref[key] = value
282+ export_device_ref.update(values)
283 try:
284 export_device_ref.save()
285 return export_device_ref
286@@ -1060,8 +1049,7 @@
287
288 def auth_create_token(_context, token):
289 tk = models.AuthToken()
290- for k, v in token.iteritems():
291- tk[k] = v
292+ tk.update(token)
293 tk.save()
294 return tk
295
296@@ -1087,8 +1075,7 @@
297 @require_admin_context
298 def quota_create(context, values):
299 quota_ref = models.Quota()
300- for (key, value) in values.iteritems():
301- quota_ref[key] = value
302+ quota_ref.update(values)
303 quota_ref.save()
304 return quota_ref
305
306@@ -1098,8 +1085,7 @@
307 session = get_session()
308 with session.begin():
309 quota_ref = quota_get(context, project_id, session=session)
310- for (key, value) in values.iteritems():
311- quota_ref[key] = value
312+ quota_ref.update(values)
313 quota_ref.save(session=session)
314
315
316@@ -1148,8 +1134,7 @@
317 @require_context
318 def volume_create(context, values):
319 volume_ref = models.Volume()
320- for (key, value) in values.iteritems():
321- volume_ref[key] = value
322+ volume_ref.update(values)
323
324 session = get_session()
325 with session.begin():
326@@ -1306,8 +1291,7 @@
327 session = get_session()
328 with session.begin():
329 volume_ref = volume_get(context, volume_id, session=session)
330- for (key, value) in values.iteritems():
331- volume_ref[key] = value
332+ volume_ref.update(values)
333 volume_ref.save(session=session)
334
335
336@@ -1400,8 +1384,7 @@
337 # FIXME(devcamcar): Unless I do this, rules fails with lazy load exception
338 # once save() is called. This will get cleaned up in next orm pass.
339 security_group_ref.rules
340- for (key, value) in values.iteritems():
341- security_group_ref[key] = value
342+ security_group_ref.update(values)
343 security_group_ref.save()
344 return security_group_ref
345
346@@ -1455,8 +1438,7 @@
347 @require_context
348 def security_group_rule_create(context, values):
349 security_group_rule_ref = models.SecurityGroupIngressRule()
350- for (key, value) in values.iteritems():
351- security_group_rule_ref[key] = value
352+ security_group_rule_ref.update(values)
353 security_group_rule_ref.save()
354 return security_group_rule_ref
355
356@@ -1508,8 +1490,7 @@
357 @require_admin_context
358 def user_create(_context, values):
359 user_ref = models.User()
360- for (key, value) in values.iteritems():
361- user_ref[key] = value
362+ user_ref.update(values)
363 user_ref.save()
364 return user_ref
365
366@@ -1537,8 +1518,7 @@
367
368 def project_create(_context, values):
369 project_ref = models.Project()
370- for (key, value) in values.iteritems():
371- project_ref[key] = value
372+ project_ref.update(values)
373 project_ref.save()
374 return project_ref
375
376@@ -1600,8 +1580,7 @@
377 session = get_session()
378 with session.begin():
379 user_ref = user_get(context, user_id, session=session)
380- for (key, value) in values.iteritems():
381- user_ref[key] = value
382+ user_ref.update(values)
383 user_ref.save(session=session)
384
385
386@@ -1609,8 +1588,7 @@
387 session = get_session()
388 with session.begin():
389 project_ref = project_get(context, project_id, session=session)
390- for (key, value) in values.iteritems():
391- project_ref[key] = value
392+ project_ref.update(values)
393 project_ref.save(session=session)
394
395
396
397=== modified file 'nova/db/sqlalchemy/models.py'
398--- nova/db/sqlalchemy/models.py 2010-10-25 06:26:03 +0000
399+++ nova/db/sqlalchemy/models.py 2010-10-28 15:46:05 +0000
400@@ -82,6 +82,16 @@
401 n = self._i.next().name
402 return n, getattr(self, n)
403
404+ def update(self, values):
405+ """Make the model object behave like a dict"""
406+ for k, v in values.iteritems():
407+ setattr(self, k, v)
408+
409+ def iteritems(self):
410+ """Make the model object behave like a dict"""
411+ return iter(self)
412+
413+
414 # TODO(vish): Store images in the database instead of file system
415 #class Image(BASE, NovaBase):
416 # """Represents an image in the datastore"""
417
418=== modified file 'nova/tests/api/openstack/fakes.py'
419--- nova/tests/api/openstack/fakes.py 2010-10-22 07:48:27 +0000
420+++ nova/tests/api/openstack/fakes.py 2010-10-28 15:46:05 +0000
421@@ -30,6 +30,7 @@
422 import nova.api.openstack.auth
423 from nova.image import service
424 from nova.image.services import glance
425+from nova.tests import fake_flags
426 from nova.wsgi import Router
427
428
429
430=== modified file 'nova/tests/api/openstack/test_servers.py'
431--- nova/tests/api/openstack/test_servers.py 2010-10-22 07:48:27 +0000
432+++ nova/tests/api/openstack/test_servers.py 2010-10-28 15:46:05 +0000
433@@ -91,9 +91,7 @@
434 pass
435
436 def instance_create(context, inst):
437- class Foo(object):
438- internal_id = 1
439- return Foo()
440+ return {'id': 1, 'internal_id': 1}
441
442 def fake_method(*args, **kwargs):
443 pass