'Detach a volume from an instance.
:param context: security context
:param bdm: nova.objects.BlockDeviceMapping volume bdm to detach
:param instance: the Instance object to detach the volume from
:param destroy_bdm: if True, the corresponding BDM entry will be marked
as deleted. Disabling this is useful for operations
like rebuild, when we don\'t want to destroy BDM
:param attachment_id: The volume attachment_id for the given instance
and volume.'

def _detach_volume(self, context, bdm, instance, destroy_bdm=True, attachment_id=None):

    volume_id = bdm.volume_id
    compute_utils.notify_about_volume_attach_detach(context, instance, self.host, action=fields.NotificationAction.VOLUME_DETACH, phase=fields.NotificationPhase.START, volume_id=volume_id)
    self._notify_volume_usage_detach(context, instance, bdm)
    LOG.info('Detaching    volume    %(volume_id)s', {'volume_id': volume_id}, instance=instance)
    driver_bdm = driver_block_device.convert_volume(bdm)
    driver_bdm.detach(context, instance, self.volume_api, self.driver, attachment_id=attachment_id, destroy_bdm=destroy_bdm)
    info = dict(volume_id=volume_id)
    self._notify_about_instance_usage(context, instance, 'volume.detach', extra_usage_info=info)
    compute_utils.notify_about_volume_attach_detach(context, instance, self.host, action=fields.NotificationAction.VOLUME_DETACH, phase=fields.NotificationPhase.END, volume_id=volume_id)
    if (('tag' in bdm) and bdm.tag):
        self._delete_disk_metadata(instance, bdm)
    if destroy_bdm:
        bdm.destroy()
