@utils.synchronized(volume_id, external=True)
def do_attach():
    volume = self.db.volume_get(context, volume_id)
    volume_metadata = self.db.volume_admin_metadata_get(context.elevated(), volume_id)
    if (volume['status'] == 'attaching'):
        if (volume_metadata.get('attached_mode') and (volume_metadata.get('attached_mode') != mode)):
            raise exception.InvalidVolume(reason=_('being attached by different mode'))
    if ((volume['status'] == 'in-use') and (not volume['multiattach']) and (not volume['migration_status'])):
        raise exception.InvalidVolume(reason=_('volume is already attached'))
    host_name_sanitized = (utils.sanitize_hostname(host_name) if host_name else None)
    if instance_uuid:
        attachments = self.db.volume_attachment_get_all_by_instance_uuid(context, volume_id, instance_uuid)
    else:
        attachments = self.db.volume_attachment_get_all_by_host(context, volume_id, host_name_sanitized)
    if attachments:
        self.db.volume_update(context, volume_id, {'status': 'in-use'})
        return
    self._notify_about_volume_usage(context, volume, 'attach.start')
    values = {'volume_id': volume_id, 'attach_status': 'attaching'}
    attachment = self.db.volume_attach(context.elevated(), values)
    volume_metadata = self.db.volume_admin_metadata_update(context.elevated(), volume_id, {'attached_mode': mode}, False)
    attachment_id = attachment['id']
    if (instance_uuid and (not uuidutils.is_uuid_like(instance_uuid))):
        self.db.volume_attachment_update(context, attachment_id, {'attach_status': 'error_attaching'})
        raise exception.InvalidUUID(uuid=instance_uuid)
    volume = self.db.volume_get(context, volume_id)
    if ((volume_metadata.get('readonly') == 'True') and (mode != 'ro')):
        self.db.volume_update(context, volume_id, {'status': 'error_attaching'})
        self.message_api.create(context, defined_messages.ATTACH_READONLY_VOLUME, context.project_id, resource_type=resource_types.VOLUME, resource_uuid=volume_id)
        raise exception.InvalidVolumeAttachMode(mode=mode, volume_id=volume_id)
    try:
        utils.require_driver_initialized(self.driver)
        LOG.debug('Attaching volume %(volume_id)s to instance %(instance)s at mountpoint %(mount)s on host %(host)s.', {'volume_id': volume_id, 'instance': instance_uuid, 'mount': mountpoint, 'host': host_name_sanitized}, resource=volume)
        self.driver.attach_volume(context, volume, instance_uuid, host_name_sanitized, mountpoint)
    except Exception:
        with excutils.save_and_reraise_exception():
            self.db.volume_attachment_update(context, attachment_id, {'attach_status': 'error_attaching'})
    volume = self.db.volume_attached(context.elevated(), attachment_id, instance_uuid, host_name_sanitized, mountpoint, mode)
    self._notify_about_volume_usage(context, volume, 'attach.end')
    LOG.info(_LI('Attach volume completed successfully.'), resource=volume)
    return self.db.volume_attachment_get(context, attachment_id)
@utils.synchronized(volume_id, external=True)
def do_attach():
    volume = self.db.volume_get(context, volume_id)
    volume_metadata = self.db.volume_admin_metadata_get(context.elevated(), volume_id)
    if (volume['status'] == 'attaching'):
        if (volume_metadata.get('attached_mode') and (volume_metadata.get('attached_mode') != mode)):
            raise exception.InvalidVolume(reason=_('being attached by different mode'))
    if ((volume['status'] == 'in-use') and (not volume['multiattach']) and (not volume['migration_status'])):
        raise exception.InvalidVolume(reason=_('volume is already attached'))
    host_name_sanitized = (utils.sanitize_hostname(host_name) if host_name else None)
    if instance_uuid:
        attachments = self.db.volume_attachment_get_all_by_instance_uuid(context, volume_id, instance_uuid)
    else:
        attachments = self.db.volume_attachment_get_all_by_host(context, volume_id, host_name_sanitized)
    if attachments:
        self.db.volume_update(context, volume_id, {'status': 'in-use'})
        return
    self._notify_about_volume_usage(context, volume, 'attach.start')
    values = {'volume_id': volume_id, 'attach_status': 'attaching'}
    attachment = self.db.volume_attach(context.elevated(), values)
    volume_metadata = self.db.volume_admin_metadata_update(context.elevated(), volume_id, {'attached_mode': mode}, False)
    attachment_id = attachment['id']
    if (instance_uuid and (not uuidutils.is_uuid_like(instance_uuid))):
        self.db.volume_attachment_update(context, attachment_id, {'attach_status': 'error_attaching'})
        raise exception.InvalidUUID(uuid=instance_uuid)
    volume = self.db.volume_get(context, volume_id)
    if ((volume_metadata.get('readonly') == 'True') and (mode != 'ro')):
        self.db.volume_update(context, volume_id, {'status': 'error_attaching'})
        self.message_api.create(context, defined_messages.ATTACH_READONLY_VOLUME, context.project_id, resource_type=resource_types.VOLUME, resource_uuid=volume_id)
        raise exception.InvalidVolumeAttachMode(mode=mode, volume_id=volume_id)
    try:
        utils.require_driver_initialized(self.driver)
        LOG.debug('Attaching volume %(volume_id)s to instance %(instance)s at mountpoint %(mount)s on host %(host)s.', {'volume_id': volume_id, 'instance': instance_uuid, 'mount': mountpoint, 'host': host_name_sanitized}, resource=volume)
        self.driver.attach_volume(context, volume, instance_uuid, host_name_sanitized, mountpoint)
    except Exception:
        with excutils.save_and_reraise_exception():
            self.db.volume_attachment_update(context, attachment_id, {'attach_status': 'error_attaching'})
    volume = self.db.volume_attached(context.elevated(), attachment_id, instance_uuid, host_name_sanitized, mountpoint, mode)
    self._notify_about_volume_usage(context, volume, 'attach.end')
    LOG.info(_LI('Attach volume completed successfully.'), resource=volume)
    return self.db.volume_attachment_get(context, attachment_id)