Cells: Commit resize quota reservations immediately

There's not an immediate good solution for quotas on resize with cells
due to how it's implemented.  Will have to revisit this with a better
patch later.  This can lead to some out-of-sync issues when deleting
things in certain resize states... or if there are resize errors.

Store migration information on API cell to correctly handle quotas

Revert and confirm of migrations require access to migration information
so they can calculate the reservation correctly. For new resizes, store
a migration record locally so it can be used later on. For old resizes,
keep the previous behavior (for now).

Implements blueprint nova-compute-cells

Change-Id: I356600d1d0d9408b019a9422f795b4244c252052
This commit is contained in:
Chris Behrens 2012-08-15 07:04:29 +00:00
parent 59333ce9f3
commit e0ac5beb4e
2 changed files with 50 additions and 13 deletions

View File

@ -92,6 +92,7 @@ CONF = cfg.CONF
CONF.register_opts(compute_opts)
CONF.import_opt('compute_topic', 'nova.compute.rpcapi')
CONF.import_opt('consoleauth_topic', 'nova.consoleauth')
CONF.import_opt('enable', 'nova.cells.opts', group='cells')
MAX_USERDATA_SIZE = 65535
QUOTAS = quota.QUOTAS
@ -1643,6 +1644,11 @@ class API(base.Base):
self.db.migration_update(elevated, migration_ref['id'],
{'status': 'reverting'})
# With cells, the best we can do right now is commit the reservations
# immediately...
if CONF.cells.enable and reservations:
QUOTAS.commit(context, reservations)
reservations = []
self.compute_rpcapi.revert_resize(context,
instance=instance, migration=migration_ref,
@ -1667,6 +1673,11 @@ class API(base.Base):
self.db.migration_update(elevated, migration_ref['id'],
{'status': 'confirming'})
# With cells, the best we can do right now is commit the reservations
# immediately...
if CONF.cells.enable and reservations:
QUOTAS.commit(context, reservations)
reservations = []
self.compute_rpcapi.confirm_resize(context,
instance=instance, migration=migration_ref,
@ -1829,6 +1840,12 @@ class API(base.Base):
if not CONF.allow_resize_to_same_host:
filter_properties['ignore_hosts'].append(instance['host'])
# With cells, the best we can do right now is commit the reservations
# immediately...
if CONF.cells.enable and reservations:
QUOTAS.commit(context, reservations)
reservations = []
args = {
"instance": instance,
"instance_type": new_instance_type,

View File

@ -18,7 +18,7 @@
from nova import block_device
from nova.cells import rpcapi as cells_rpcapi
from nova.compute import api as compute_api
from nova.compute import task_states
from nova.compute import instance_types
from nova.compute import vm_states
from nova import exception
from nova.openstack.common import excutils
@ -241,22 +241,14 @@ class ComputeCellsAPI(compute_api.API):
@validate_cell
def revert_resize(self, context, instance):
"""Reverts a resize, deleting the 'new' instance in the process."""
# NOTE(markwash): regular api manipulates the migration here, but we
# don't have access to it. So to preserve the interface just update the
# vm and task state.
self.update(context, instance,
task_state=task_states.RESIZE_REVERTING)
super(ComputeCellsAPI, self).revert_resize(context, instance)
self._cast_to_cells(context, instance, 'revert_resize')
@check_instance_state(vm_state=[vm_states.RESIZED])
@validate_cell
def confirm_resize(self, context, instance):
"""Confirms a migration/resize and deletes the 'old' instance."""
# NOTE(markwash): regular api manipulates migration here, but we don't
# have the migration in the api database. So to preserve the interface
# just update the vm and task state without calling super()
self.update(context, instance, task_state=None,
vm_state=vm_states.ACTIVE)
super(ComputeCellsAPI, self).confirm_resize(context, instance)
self._cast_to_cells(context, instance, 'confirm_resize')
@check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.STOPPED],
@ -269,8 +261,36 @@ class ComputeCellsAPI(compute_api.API):
the original flavor_id. If flavor_id is not None, the instance should
be migrated to a new host and resized to the new flavor_id.
"""
super(ComputeCellsAPI, self).resize(context, instance, *args,
**kwargs)
super(ComputeCellsAPI, self).resize(context, instance, *args, **kwargs)
# NOTE(johannes): If we get to this point, then we know the
# specified flavor_id is valid and exists. We'll need to load
# it again, but that should be safe.
old_instance_type_id = instance['instance_type_id']
old_instance_type = instance_types.get_instance_type(
old_instance_type_id)
flavor_id = kwargs.get('flavor_id')
if not flavor_id:
new_instance_type = old_instance_type
else:
new_instance_type = instance_types.get_instance_type_by_flavor_id(
flavor_id)
# NOTE(johannes): Later, when the resize is confirmed or reverted,
# the superclass implementations of those methods will need access
# to a local migration record for quota reasons. We don't need
# source and/or destination information, just the old and new
# instance_types. Status is set to 'finished' since nothing else
# will update the status along the way.
self.db.migration_create(context.elevated(),
{'instance_uuid': instance['uuid'],
'old_instance_type_id': old_instance_type['id'],
'new_instance_type_id': new_instance_type['id'],
'status': 'finished'})
# FIXME(comstud): pass new instance_type object down to a method
# that'll unfold it
self._cast_to_cells(context, instance, 'resize', *args, **kwargs)