summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2011-12-15 06:16:18 +0000
committerGerrit Code Review <review@openstack.org>2011-12-15 06:16:18 +0000
commit076317047802d3ed393c5467223abd6f613291ba (patch)
treeebe50ea7acf197a13ff35c6260a1413072fafbc5
parent548ae0bdbf70e425dd4aca65f98038c2ae65d1f4 (diff)
parent31a7924ecfae0b9c9fea0edc344f0e3ca2fe78a5 (diff)
Merge "Refactors handling of detach volume"
-rw-r--r--nova/compute/manager.py142
1 files changed, 72 insertions, 70 deletions
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index d75aad603..d6912bb56 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -33,7 +33,6 @@ terminating it.
"""
-import datetime
import functools
import os
import socket
@@ -146,6 +145,7 @@ class ComputeManager(manager.SchedulerDependentManager):
sys.exit(1)
self.network_api = network.API()
+ self.volume_api = volume.API()
self.network_manager = utils.import_object(FLAGS.network_manager)
self._last_host_check = 0
self._last_bw_usage_poll = 0
@@ -245,7 +245,6 @@ class ComputeManager(manager.SchedulerDependentManager):
def _setup_block_device_mapping(self, context, instance):
"""setup volumes for block device mapping"""
- volume_api = volume.API()
block_device_mapping = []
swap = None
ephemerals = []
@@ -273,18 +272,18 @@ class ComputeManager(manager.SchedulerDependentManager):
if ((bdm['snapshot_id'] is not None) and
(bdm['volume_id'] is None)):
# TODO(yamahata): default name and description
- vol = volume_api.create(context, bdm['volume_size'],
- bdm['snapshot_id'], '', '')
+ vol = self.volume_api.create(context, bdm['volume_size'],
+ bdm['snapshot_id'], '', '')
# TODO(yamahata): creating volume simultaneously
# reduces creation time?
- volume_api.wait_creation(context, vol['id'])
+ self.volume_api.wait_creation(context, vol['id'])
self.db.block_device_mapping_update(
context, bdm['id'], {'volume_id': vol['id']})
bdm['volume_id'] = vol['id']
if bdm['volume_id'] is not None:
- volume_api.check_attach(context,
- volume_id=bdm['volume_id'])
+ self.volume_api.check_attach(context,
+ volume_id=bdm['volume_id'])
cinfo = self._attach_volume_boot(context, instance,
bdm['volume_id'],
bdm['device_name'])
@@ -507,6 +506,15 @@ class ComputeManager(manager.SchedulerDependentManager):
instance_id)
return [bdm for bdm in bdms if bdm['volume_id']]
+ def _get_instance_volume_bdm(self, context, instance_id, volume_id):
+ bdms = self._get_instance_volume_bdms(context, instance_id)
+ for bdm in bdms:
+ # NOTE(vish): Comparing as strings because the os_api doesn't
+ # convert to integer and we may wish to support uuids
+ # in the future.
+ if str(bdm['volume_id']) == str(volume_id):
+ return bdm
+
def _get_instance_volume_block_device_info(self, context, instance_id):
bdms = self._get_instance_volume_bdms(context, instance_id)
block_device_mapping = []
@@ -515,8 +523,8 @@ class ComputeManager(manager.SchedulerDependentManager):
block_device_mapping.append({'connection_info': cinfo,
'mount_device':
bdm['device_name']})
- ## NOTE(vish): The mapping is passed in so the driver can disconnect
- ## from remote volumes if necessary
+ # NOTE(vish): The mapping is passed in so the driver can disconnect
+ # from remote volumes if necessary
return {'block_device_mapping': block_device_mapping}
@exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
@@ -546,29 +554,33 @@ class ComputeManager(manager.SchedulerDependentManager):
if not FLAGS.stub_network:
self.network_api.deallocate_for_instance(context, instance)
- for bdm in self._get_instance_volume_bdms(context, instance_id):
- volume_id = bdm['volume_id']
- try:
- self._detach_volume(context, instance_uuid, volume_id)
- except exception.DiskNotFound as exc:
- LOG.warn(_("Ignoring DiskNotFound: %s") % exc)
-
if instance['power_state'] == power_state.SHUTOFF:
self.db.instance_destroy(context, instance_id)
raise exception.Error(_('trying to destroy already destroyed'
' instance: %s') % instance_uuid)
+ # NOTE(vish) get bdms before destroying the instance
+ bdms = self._get_instance_volume_bdms(context, instance_id)
block_device_info = self._get_instance_volume_block_device_info(
context, instance_id)
self.driver.destroy(instance, network_info, block_device_info, cleanup)
+ for bdm in bdms:
+ try:
+ # NOTE(vish): actual driver detach done in driver.destroy, so
+ # just tell nova-volume that we are done with it.
+ self.volume_api.terminate_connection(context,
+ bdm['volume_id'],
+ FLAGS.my_ip)
+ self.volume_api.detach(context, bdm['volume_id'])
+ except exception.DiskNotFound as exc:
+ LOG.warn(_("Ignoring DiskNotFound: %s") % exc)
def _cleanup_volumes(self, context, instance_id):
- volume_api = volume.API()
bdms = self.db.block_device_mapping_get_all_by_instance(context,
instance_id)
for bdm in bdms:
LOG.debug(_("terminating bdm %s") % bdm)
if bdm['volume_id'] and bdm['delete_on_termination']:
- volume_api.delete(context, bdm['volume_id'])
+ self.volume_api.delete(context, bdm['volume_id'])
# NOTE(vish): bdms will be deleted on instance destroy
def _delete_instance(self, context, instance):
@@ -1400,13 +1412,13 @@ class ComputeManager(manager.SchedulerDependentManager):
"volume %(volume_id)s at %(mountpoint)s") %
locals(), context=context)
address = FLAGS.my_ip
- volume_api = volume.API()
- connection_info = volume_api.initialize_connection(context,
- volume_id,
- address)
- volume_api.attach(context, volume_id, instance_id, mountpoint)
+ connection_info = self.volume_api.initialize_connection(context,
+ volume_id,
+ address)
+ self.volume_api.attach(context, volume_id, instance_id, mountpoint)
return connection_info
+ @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
@checks_instance_lock
def attach_volume(self, context, instance_uuid, volume_id, mountpoint):
"""Attach a volume to an instance."""
@@ -1416,11 +1428,10 @@ class ComputeManager(manager.SchedulerDependentManager):
LOG.audit(
_("instance %(instance_uuid)s: attaching volume %(volume_id)s"
" to %(mountpoint)s") % locals(), context=context)
- volume_api = volume.API()
address = FLAGS.my_ip
- connection_info = volume_api.initialize_connection(context,
- volume_id,
- address)
+ connection_info = self.volume_api.initialize_connection(context,
+ volume_id,
+ address)
try:
self.driver.attach_volume(connection_info,
instance_ref['name'],
@@ -1432,10 +1443,10 @@ class ComputeManager(manager.SchedulerDependentManager):
# ecxception below.
LOG.exception(_("instance %(instance_uuid)s: attach failed"
" %(mountpoint)s, removing") % locals(), context=context)
- volume_api.terminate_connection(context, volume_id, address)
+ self.volume_api.terminate_connection(context, volume_id, address)
raise exc
- volume_api.attach(context, volume_id, instance_id, mountpoint)
+ self.volume_api.attach(context, volume_id, instance_id, mountpoint)
values = {
'instance_id': instance_id,
'connection_info': utils.dumps(connection_info),
@@ -1449,60 +1460,51 @@ class ComputeManager(manager.SchedulerDependentManager):
self.db.block_device_mapping_create(context, values)
return True
- @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
- @checks_instance_lock
- def _detach_volume(self, context, instance_uuid, volume_id,
- destroy_bdm=False, mark_detached=True,
- force_detach=False):
- """Detach a volume from an instance."""
- context = context.elevated()
- instance_ref = self.db.instance_get_by_uuid(context, instance_uuid)
- instance_id = instance_ref['id']
- bdms = self.db.block_device_mapping_get_all_by_instance(
- context, instance_id)
- for item in bdms:
- # NOTE(vish): Comparing as strings because the os_api doesn't
- # convert to integer and we may wish to support uuids
- # in the future.
- if str(item['volume_id']) == str(volume_id):
- bdm = item
- break
+ def _detach_volume(self, context, instance_name, bdm):
+ """Do the actual driver detach using block device mapping."""
mp = bdm['device_name']
+ volume_id = bdm['volume_id']
LOG.audit(_("Detach volume %(volume_id)s from mountpoint %(mp)s"
- " on instance %(instance_id)s") % locals(), context=context)
- volume_api = volume.API()
- if (instance_ref['name'] not in self.driver.list_instances() and
- not force_detach):
+ " on instance %(instance_name)s") % locals(), context=context)
+
+ if instance_name not in self.driver.list_instances():
LOG.warn(_("Detaching volume from unknown instance %s"),
- instance_id, context=context)
- else:
- self.driver.detach_volume(utils.loads(bdm['connection_info']),
- instance_ref['name'],
- bdm['device_name'])
- address = FLAGS.my_ip
- volume_api.terminate_connection(context, volume_id, address)
- if mark_detached:
- volume_api.detach(context, volume_id)
- if destroy_bdm:
- self.db.block_device_mapping_destroy_by_instance_and_volume(
- context, instance_id, volume_id)
- return True
+ instance_name, context=context)
+ self.driver.detach_volume(utils.loads(bdm['connection_info']),
+ instance_name,
+ mp)
+ @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
+ @checks_instance_lock
def detach_volume(self, context, instance_uuid, volume_id):
"""Detach a volume from an instance."""
- return self._detach_volume(context, instance_uuid, volume_id, True)
+ instance_ref = self.db.instance_get_by_uuid(context, instance_uuid)
+ instance_id = instance_ref['id']
+ bdm = self._get_instance_volume_bdm(context, instance_id, volume_id)
+ self._detach_volume(context, instance_ref['name'], bdm)
+ self.volume_api.terminate_connection(context, volume_id, FLAGS.my_ip)
+ self.volume_api.detach(context, volume_id)
+ self.db.block_device_mapping_destroy_by_instance_and_volume(
+ context, instance_id, volume_id)
+ return True
@exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
def remove_volume_connection(self, context, instance_id, volume_id):
- """Detach a volume from an instance.,"""
+ """Remove a volume connection using the volume api"""
# NOTE(vish): We don't want to actually mark the volume
# detached, or delete the bdm, just remove the
# connection from this host.
try:
instance_ref = self.db.instance_get(context, instance_id)
- self._detach_volume(context, instance_ref['uuid'], volume_id,
- False, False, True)
+ bdm = self._get_instance_volume_bdm(context,
+ instance_id,
+ volume_id)
+ self._detach_volume(context, instance_ref['name'],
+ bdm['volume_id'], bdm['device_name'])
+ self.volume_api.terminate_connection(context,
+ volume_id,
+ FLAGS.my_ip)
except exception.NotFound:
pass
@@ -1821,8 +1823,8 @@ class ComputeManager(manager.SchedulerDependentManager):
for bdm in self._get_instance_volume_bdms(context, instance_ref['id']):
volume_id = bdm['volume_id']
self.db.volume_update(context, volume_id, {'status': 'in-use'})
- volume.API().remove_from_compute(context, instance_ref['id'],
- volume_id, dest)
+ self.volume_api.remove_from_compute(context, instance_ref['id'],
+ volume_id, dest)
# Block migration needs empty image at destination host
# before migration starts, so if any failure occurs,