'Detach a volume from an instance.'

@wsgi.response(202)
@extensions.expected_errors((400, 403, 404, 409))
def delete(self, req, server_id, id):

    context = req.environ['nova.context']
    context.can((va_policies.POLICY_ROOT % 'delete'))
    volume_id = id
    instance = common.get_instance(self.compute_api, context, server_id, expected_attrs=['device_metadata'])
    if (instance.vm_state in (vm_states.SHELVED, vm_states.SHELVED_OFFLOADED)):
        _check_request_version(req, '2.20', 'detach_volume', server_id, instance.vm_state)
    try:
        volume = self.volume_api.get(context, volume_id)
    except exception.VolumeNotFound as e:
        raise exc.HTTPNotFound(explanation=e.format_message())
    bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(context, instance.uuid)
    if (not bdms):
        msg = (_('Instance    %s    is    not    attached.') % server_id)
        raise exc.HTTPNotFound(explanation=msg)
    found = False
    try:
        for bdm in bdms:
            if (bdm.volume_id != volume_id):
                continue
            if bdm.is_root:
                msg = _("Can't    detach    root    device    volume")
                raise exc.HTTPForbidden(explanation=msg)
            try:
                self.compute_api.detach_volume(context, instance, volume)
                found = True
                break
            except exception.InvalidVolume as e:
                raise exc.HTTPBadRequest(explanation=e.format_message())
            except exception.InstanceUnknownCell as e:
                raise exc.HTTPNotFound(explanation=e.format_message())
            except exception.InvalidInput as e:
                raise exc.HTTPBadRequest(explanation=e.format_message())
    except exception.InstanceIsLocked as e:
        raise exc.HTTPConflict(explanation=e.format_message())
    except exception.InstanceInvalidState as state_error:
        common.raise_http_conflict_for_instance_invalid_state(state_error, 'detach_volume', server_id)
    if (not found):
        msg = (_('volume_id    not    found:    %s') % volume_id)
        raise exc.HTTPNotFound(explanation=msg)
