Merge "Refactors handling of detach volume"

This commit is contained in:
Jenkins
2011-12-15 06:16:18 +00:00
committed by Gerrit Code Review

View File

@@ -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):
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
" 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_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,