用户界面“失败”消息和事件查看器

长期以来,OpenStack 服务一直希望能够向 API 端用户(这里用户指的是与 API 交互的用户,而非操作员)发送消息,尤其是错误消息。

如果用户执行某个操作,并且该操作失败或进入挂起状态,那么必须存在某种接口让用户能够查看此行为的原因。

因此,这基本上是关于促进用户通过 API 或 Horizon 中的新“事件查看器”选项卡或 Horizon 插件直接查看异步操作的错误消息。

这更具体地针对失败的操作及其失败原因。

https://blueprints.launchpad.net/cinder/+spec/summarymessage

问题描述

如果创建卷、创建快照等操作失败,用户在操作失败时无法获得详细信息。有时,只有操作状态更新为错误、失败等,而没有向用户更新任何信息。

在某些情况下,情况更糟。例如,1. 如果 rabbitmq 不活动,用户尝试创建卷,Horizon 会永远挂起等待 API 的响应。 2. 如果 rabbitmq 处于活动状态,但接收服务未运行,用户尝试创建卷,API 会永远挂起等待 rabbitMQ 的响应。

在所有 OpenStack 项目中,只有少数资源能够处理向异步操作的最终用户报告错误,并且那些能够处理的资源之间也不一致。除了提供一种在 OpenStack 中一致地启用错误报告的机制外,该解决方案还必须能够适应不包含任何其他 OpenStack 服务的 Cinder 部署。

用例

此蓝图的动机

  1. 帮助管理员在减少日志过滤的情况下调试失败的操作。

  2. 通知管理员启动由于某些异常情况而失败的服务。

  3. 在操作失败时通知用户。

  4. 向用户提供有关失败的足够信息。

通用用例

  • Cinder 卷/快照创建进入 ERROR 状态,由于容量不足。(调度错误)

  • Cinder 将卷添加到 CG 失败,如何告诉用户卷和组不在同一后端?

  • Cinder 卷从附加到可用状态。为什么?

  • 卷重类型失败。

  • 卷扩展失败,我想知道原因,并且能够继续使用我的卷,而不是使其处于 error_extending 状态。

  • 等等…

提议的变更

用户可以通过直接 API 调用或通过新的 Horizon 选项卡“事件查看器”获取操作失败的详细信息。通过 CLI,可以使用 cli 客户端显示相同类型的信息。

建议的实现基于双向方法

  1. 推送信息:在用户操作期间,将使用特定于组件的通知将消息推送到数据库。

    这些消息将由组件为操作开始、操作完成或操作失败生成并推送到数据库。

    消息生成将基于事件 ID 到事件消息的映射,使用包含不同通知消息映射的消息常量文件。 这样,部署者可以根据需要轻松修改通知消息。

  2. 拉取信息:如果用户需要检查操作状态,用户可以使用 CLI 客户端或 Horizon 选项卡拉取详细信息。

结果可以以表格形式显示,如下所示

租户

EventID

NodeName

ReqID

Level

Resource

Time

Summary

Sheel

UKN_ERR

BS-cind1

{…}

Error

Volume

{..}

{….}

每个用户发起的“操作”都有一个请求 ID,作为 HTTP 标头包含在上下文中。这些通知消息将与操作请求 ID 关联。(此请求 ID 将用于将请求映射到 cinder 为该操作所发生的事情。)

摘要消息将包含特定于操作的失败消息。例如,“卷创建操作失败 - {失败原因}”

过滤器

可以根据 TenantID、HostID、UserID、Operation Outcome/Result(Fail/Pass) 等过滤结果。

消息类型

  1. API 事件:用于失败操作的消息。

  2. 服务日志:用于失败的服务的信息,这些服务由用户停止或由于任何异常情况而停止。

  3. 系统日志:API 和服务日志之外的任何其他日志。

建议的架构:

拟议的更改是在 Cinder DB 中添加一个新的 /v3//messages API 资源,并添加一个消息表来支持该资源。此端点将返回一个关于异步操作失败的、供最终用户使用的错误消息列表。

简而言之:* /v3//messages API 资源,根据过滤器公开通知消息 * message_ttl 配置选项,规定消息在数据库中的最小生存时间(秒)* messages DB 表

问题

备选方案

  • 用户界面通知 使用现有的通知框架与 AMQP 消费者结合,以拉取消息并提供用户端点。此方法的缺点是不希望向用户显示当前通知中的信息,并且需要更多服务作为依赖项。

  • 每个资源的故障 此替代方案建议向每个资源添加一个子资源,例如 volumes//faults,类似于 Nova 的实例故障。这使得轮询多个资源或资源类型的消息变得困难。它还为 API 增加了显著的复杂性,因为每个资源都必须添加 /faults 才能支持消息。

  • 通过单独的服务(例如 Zaqar)公开用户消息 此方法建议将用户消息存储在另一个服务中,用户可以查询该服务以获取消息,或者该服务可以使用 Webhooks 向用户发送通知。此方法的的主要缺点是编写绑定到单独服务(s) 的复杂性以及需要单独服务作为依赖项。

此规范未解决的问题

  • 状态更改通知。此解决方案不打算解决在卷或任何其他资源更改状态时向用户发出警报的用例。例如,当卷从 creating 更改为 available 时。

REST API 影响

新的 API:* GET /v3//messages 带有按属性过滤。例如:GET /v3//messages?resource_type=volume * GET /v3//messages/ * DELETE /v3//messages/

消息模式

Message:
  type: object
  required:
  - user_message
  - id
  - project_id
  - request_id
  - event_id
  - created_at
  - message_level
  - expires_at
  properties:
    id:
      type: string
      description: UUID will be stored in 'id' field.
    message_level:
      type: string
      enum:
      - ERROR
      description: The level of the message. In the future we may expand to
      sending information to the user that is not an error.
    user_message:
      type: string
    event_id:
      type: string
      description: Event ID can be used to
      a. update message text at deployer end for some specific situation.
      b. to report errors by user.
      c. to debug fast as it is easy to search where specific eventID is
      used for reporting error.
    resource_uuid:
      type: string
      description: The uuid of the offending resource.
    resource_type:
      type: string
      description: The type of resource this message pertains to.
      For ex, volume, snapshot, backup etc
    request_id:
      type: string
    created_at:
      type: string
    expires_at:
      type: string
      description: After this time the message may no longer exist

数据模型影响

DB 中新的消息表,用于存储所有消息。此表可能会在具有大量错误的云中变得很大。管理员可以使用 expires_at 列来清除消息。

安全影响

在向用户显示消息之前,必须对消息进行严格审查,以避免显示任何敏感数据。这将通过将所有用户可见的消息定义在单个模块中来缓解。消息机制将断言它创建的任何消息都来自授权位置。

通知影响

其他最终用户影响

性能影响

其他部署者影响

  • 新的配置选项 message_ttl,它将规定生成消息后,设置消息的 ‘guaranteed_until’ 属性的时间(秒)。

  • 新的配置选项 message_reap_interval,它将规定删除旧消息的间隔时间(秒)。值为 -1 将永远不会运行。

  • 新的配置选项 message_reap_batch_size,它规定每次间隔要删除的已过期消息的数量。这允许部署者通过设置一次删除的消息数量上限来限制 DB 性能影响。

  • 消息表可能很大,并且可以根据 ‘guaranteed_until’ 列进行清除。其中,所有 expires_at 日期早于当前时间的的消息都可以安全删除。

开发人员影响

开发人员应注意用户需要有关错误信息的情况。在这些情况下,应编写适当的用户消息,并在特定的代码路径中添加消息的创建。

实现

负责人

主要负责人

Sheel Rana Alex Meade

工作项

整个实现依赖于不同失败消息的生成、传输、收集、存储和分析。

  • cinder:在所有现有操作失败时生成通知消息的实现。

  • cinder:需要一个通知监听器,它将作为处理来自不同组件的事件消息的基础。

  • cinder:需要一个收集器来收集、验证和将事件消息存储到数据库。

  • cinder:新的 API,用于根据过滤器从数据库中获取详细信息。

  • cinder:为消息添加分页

  • cinder-manage:添加一种机制,以便根据 ttl 值自动地,并通过 cinder-manage 命令清除数据库中过期的消息。

  • cinder:新的 API 详细信息的文档。

  • cinder:更新“入门指南”。

  • cinder:数据库模式准备,用于存储通知消息。

  • cinder:需要实现“在消息过期时间后从数据库中删除消息”。例如,如果用户将 message_ttl 设置为 7 天,则所有早于 7 天的消息都将从数据库中清除。

  • horizon:Cinder 的单独选项卡,用于显示事件消息。

  • cinder-client:cinder cli 与 API 通信并获取事件消息。

  • cinder-client:更新 CLI 参考指南。

  • Tempest 测试

实施阶段:

整个功能将分多个阶段实现

阶段 1. 关于通知生成和存储到数据库的基本实现,以及暴露“/messages”以查看通知消息。此规范首先针对阶段 1,其他阶段将在接受阶段 1 后实现。

阶段 2. 实现,以促进管理员配置通知存储,例如 db 或 zaqar 或两者。如果管理员配置了两者,通知消息将与存储到数据库一起存储在 zaqar 中。

阶段 3. 实现,以直接从 zaqar 消费信息。

阶段 4. Horizon 和 CLI 实现,以更格式化的方式查看通知。

阶段 5. 处理某些特殊情况,这些情况需要单独处理通知生成,例如与 rabbitMQ 相关的实现,用于在 rabbitMQ 处于失败状态或 rabbitMQ 接收者处于非活动状态时显示通知。

依赖项

测试

应编写 Tempest 测试并在 gate 中运行。由于只有在发生错误时才会创建消息,因此实现完整的函数测试可能很困难。但是,一些操作很容易通过无限配额来触发失败。一个例子是创建大于后端存储容量的厚置备卷。

示例测试用例

# 列出没有消息的消息 # 尝试创建过大的卷,并验证是否创建了适当的调度错误消息 # 使用过滤器列出消息,尤其是 resource_type

文档影响

  • REST API 文档

  • 新的配置选项,message_ttl(生存时间)

  • 新的配置选项,message_reap_interval(删除旧消息的间隔时间,秒)

  • 新的配置选项,message_reap_batch_size(一次可以删除的消息数量)

  • 消息的新 API 策略

参考资料

Mitaka 中期讨论

https://etherpad.openstack.org/p/mitaka-cinder-midcycle-user-notifications https://etherpad.openstack.org/p/mitaka-cinder-midcycle-day-1

Kilo Summit 讨论

https://etherpad.openstack.org/p/kilo-cinder-async-reporting

Liberty Summit 讨论(与 HEAT 结合)-

https://etherpad.openstack.org/p/liberty-cross-project-user-notifications