审计的版本化通知

https://blueprints.launchpad.net/watcher/+spec/audit-versioned-notifications-api

在实施 watcher-notifications-ovo 蓝图 之后,Watcher 现在具备在其代码库中提供版本化通知的所有必要前提条件。此蓝图将重点描述在 Watcher 中关于 审计 对象实施的通知。

问题描述

目前,任何服务(包括 Watcher)都无法得知审计何时被创建、修改或删除。这阻止了任何形式的基于事件的反应,这对于第三方服务或插件可能很有用。

用例

作为 OpenStack 开发者,我希望能够监听来自 Watcher 关于审计的通知。

作为 OpenStack 开发者,我想知道审计通知的格式是什么。

作为 OpenStack 开发者,我希望在以下情况下收到通知:

  • 已创建审计

  • 审计已完成

作为 OpenStack 开发者,我还希望在以下情况下收到通知:

  • 审计开始执行其策略(策略由 决策引擎 触发)

  • 审计完成其策略的执行(策略已完成并生成了行动计划)

作为 OpenStack 开发者,我还希望在以下情况下收到通知:

提议的变更

为了实现上述用例,需要许多不同的通知

  • audit.create 每当创建审计时。

  • audit.update 每当审计被更新时。这包括所有状态更新,包括审计的删除。

  • audit.delete 每当审计被删除(软删除)时。

  • audit.strategy.start 每当审计开始时。

  • audit.strategy.end 每当审计结束时。

  • audit.strategy.error 每当审计失败时。

  • audit.planner.start 每当审计解决方案的规划开始时。

  • audit.planner.end 每当审计解决方案的规划结束时。

  • audit.planner.error 每当审计解决方案的规划失败时。

此外,我们将依赖 oslo.versionedobjects 来版本化与审计相关的通知的有效负载。

以下是针对上述每个事件的通知结构建议

audit.create

{
  "priority": "INFO",
  "payload": {
    "watcher_object.data": {
      "audit_type": "ONESHOT",
      "parameters": {
        "para2": "hello",
        "para1": 3.2
      },
      "state": "PENDING",
      "updated_at": null,
      "deleted_at": null,
      "goal": {
        "watcher_object.data": {
          "uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
          "name": "dummy",
          "updated_at": null,
          "deleted_at": null,
          "efficacy_specification": [],
          "created_at": "2016-11-04T16:25:35Z",
          "display_name": "Dummy goal"
        },
        "watcher_object.name": "GoalPayload",
        "watcher_object.version": "1.0",
        "watcher_object.namespace": "watcher"
      },
      "interval": null,
      "scope": [],
      "strategy": {
        "watcher_object.data": {
          "parameters_spec": {
            "properties": {
              "para2": {
                "type": "string",
                "default": "hello",
                "description": "string parameter example"
              },
              "para1": {
                "description": "number parameter example",
                "maximum": 10.2,
                "type": "number",
                "default": 3.2,
                "minimum": 1.0
              }
            }
          },
          "name": "dummy",
          "uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
          "updated_at": null,
          "deleted_at": null,
          "created_at": "2016-11-04T16:25:35Z",
          "display_name": "Dummy strategy"
        },
        "watcher_object.name": "StrategyPayload",
        "watcher_object.version": "1.0",
        "watcher_object.namespace": "watcher"
      },
      "created_at": "2016-11-04T16:29:20Z",
      "uuid": "4a97b9dd-2023-43dc-b713-815bdd94d4d6"
    },
    "watcher_object.name": "AuditCreatePayload",
    "watcher_object.version": "1.0",
    "watcher_object.namespace": "watcher"
  },
  "publisher_id": "infra-optim:localhost",
  "timestamp": "2016-11-04 16:31:36.264673   ",
  "event_type": "audit.create",
  "message_id": "cbcf9f2c-7c53-4b4d-91ec-db49cca024b6"
}

audit.update

{
  "publisher_id": "infra-optim:localhost",
  "timestamp": "2016-11-04 16:51:38.722986   ",
  "payload": {
    "watcher_object.name": "AuditUpdatePayload",
    "watcher_object.data": {
      "strategy": {
        "watcher_object.name": "StrategyPayload",
        "watcher_object.data": {
          "name": "dummy",
          "parameters_spec": {
            "properties": {
              "para2": {
                "default": "hello",
                "type": "string",
                "description": "string parameter example"
              },
              "para1": {
                "maximum": 10.2,
                "default": 3.2,
                "minimum": 1.0,
                "description": "number parameter example",
                "type": "number"
              }
            }
          },
          "updated_at": null,
          "display_name": "Dummy strategy",
          "deleted_at": null,
          "uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
          "created_at": "2016-11-04T16:25:35Z"
        },
        "watcher_object.namespace": "watcher",
        "watcher_object.version": "1.0"
      },
      "scope": [],
      "created_at": "2016-11-04T16:51:21Z",
      "uuid": "f1e0d912-afd9-4bf2-91ef-c99cd08cc1ef",
      "goal": {
        "watcher_object.name": "GoalPayload",
        "watcher_object.data": {
          "efficacy_specification": [],
          "updated_at": null,
          "name": "dummy",
          "display_name": "Dummy goal",
          "deleted_at": null,
          "uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
          "created_at": "2016-11-04T16:25:35Z"
        },
        "watcher_object.namespace": "watcher",
        "watcher_object.version": "1.0"
      },
      "parameters": {
        "para2": "hello",
        "para1": 3.2
      },
      "deleted_at": null,
      "state_update": {
        "watcher_object.name": "AuditStateUpdatePayload",
        "watcher_object.data": {
          "state": "ONGOING",
          "old_state": "PENDING"
        },
        "watcher_object.namespace": "watcher",
        "watcher_object.version": "1.0"
      },
      "interval": null,
      "updated_at": null,
      "state": "ONGOING",
      "audit_type": "ONESHOT"
    },
    "watcher_object.namespace": "watcher",
    "watcher_object.version": "1.0"
  },
  "priority": "INFO",
  "event_type": "audit.update",
  "message_id": "697fdf55-7252-4b6c-a2c2-5b9e85f6342c"
}

audit.delete

{
  "priority": "INFO",
  "payload": {
    "watcher_object.data": {
      "audit_type": "ONESHOT",
      "parameters": {
        "para2": "hello",
        "para1": 3.2
      },
      "state": "DELETED",
      "updated_at": null,
      "deleted_at": null,
      "goal": {
        "watcher_object.data": {
          "uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
          "name": "dummy",
          "updated_at": null,
          "deleted_at": null,
          "efficacy_specification": [],
          "created_at": "2016-11-04T16:25:35Z",
          "display_name": "Dummy goal"
        },
        "watcher_object.name": "GoalPayload",
        "watcher_object.version": "1.0",
        "watcher_object.namespace": "watcher"
      },
      "interval": null,
      "scope": [],
      "strategy": {
        "watcher_object.data": {
          "parameters_spec": {
            "properties": {
              "para2": {
                "type": "string",
                "default": "hello",
                "description": "string parameter example"
              },
              "para1": {
                "description": "number parameter example",
                "maximum": 10.2,
                "type": "number",
                "default": 3.2,
                "minimum": 1.0
              }
            }
          },
          "name": "dummy",
          "uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
          "updated_at": null,
          "deleted_at": null,
          "created_at": "2016-11-04T16:25:35Z",
          "display_name": "Dummy strategy"
        },
        "watcher_object.name": "StrategyPayload",
        "watcher_object.version": "1.0",
        "watcher_object.namespace": "watcher"
      },
      "created_at": "2016-11-04T16:29:20Z",
      "uuid": "4a97b9dd-2023-43dc-b713-815bdd94d4d6"
    },
    "watcher_object.name": "AuditDeletePayload",
    "watcher_object.version": "1.0",
    "watcher_object.namespace": "watcher"
  },
  "publisher_id": "infra-optim:localhost",
  "timestamp": "2016-11-04 16:31:36.264673   ",
  "event_type": "audit.delete",
  "message_id": "cbcf9f2c-7c53-4b4d-91ec-db49cca024b6"
}

audit.strategy.start

{
  "priority": "INFO",
  "payload": {
    "watcher_object.data": {
      "audit_type": "ONESHOT",
      "parameters": {
        "para2": "hello",
        "para1": 3.2
      },
      "state": "ONGOING",
      "updated_at": null,
      "deleted_at": null,
      "fault": null,
      "goal": {
        "watcher_object.data": {
          "uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
          "name": "dummy",
          "updated_at": null,
          "deleted_at": null,
          "efficacy_specification": [],
          "created_at": "2016-11-04T16:25:35Z",
          "display_name": "Dummy goal"
        },
        "watcher_object.name": "GoalPayload",
        "watcher_object.version": "1.0",
        "watcher_object.namespace": "watcher"
      },
      "interval": null,
      "scope": [],
      "strategy": {
        "watcher_object.data": {
          "parameters_spec": {
            "properties": {
              "para2": {
                "type": "string",
                "default": "hello",
                "description": "string parameter example"
              },
              "para1": {
                "description": "number parameter example",
                "maximum": 10.2,
                "type": "number",
                "default": 3.2,
                "minimum": 1.0
              }
            }
          },
          "name": "dummy",
          "uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
          "updated_at": null,
          "deleted_at": null,
          "created_at": "2016-11-04T16:25:35Z",
          "display_name": "Dummy strategy"
        },
        "watcher_object.name": "StrategyPayload",
        "watcher_object.version": "1.0",
        "watcher_object.namespace": "watcher"
      },
      "created_at": "2016-11-04T16:29:20Z",
      "uuid": "4a97b9dd-2023-43dc-b713-815bdd94d4d6"
    },
    "watcher_object.name": "AuditActionPayload",
    "watcher_object.version": "1.0",
    "watcher_object.namespace": "watcher"
  },
  "publisher_id": "infra-optim:localhost",
  "timestamp": "2016-11-04 16:31:36.264673   ",
  "event_type": "audit.strategy.start",
  "message_id": "cbcf9f2c-7c53-4b4d-91ec-db49cca024b6"
}

audit.strategy.end

{
  "priority": "INFO",
  "payload": {
    "watcher_object.data": {
      "audit_type": "ONESHOT",
      "parameters": {
        "para2": "hello",
        "para1": 3.2
      },
      "state": "ONGOING",
      "updated_at": null,
      "deleted_at": null,
      "fault": null,
      "goal": {
        "watcher_object.data": {
          "uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
          "name": "dummy",
          "updated_at": null,
          "deleted_at": null,
          "efficacy_specification": [],
          "created_at": "2016-11-04T16:25:35Z",
          "display_name": "Dummy goal"
        },
        "watcher_object.name": "GoalPayload",
        "watcher_object.version": "1.0",
        "watcher_object.namespace": "watcher"
      },
      "interval": null,
      "scope": [],
      "strategy": {
        "watcher_object.data": {
          "parameters_spec": {
            "properties": {
              "para2": {
                "type": "string",
                "default": "hello",
                "description": "string parameter example"
              },
              "para1": {
                "description": "number parameter example",
                "maximum": 10.2,
                "type": "number",
                "default": 3.2,
                "minimum": 1.0
              }
            }
          },
          "name": "dummy",
          "uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
          "updated_at": null,
          "deleted_at": null,
          "created_at": "2016-11-04T16:25:35Z",
          "display_name": "Dummy strategy"
        },
        "watcher_object.name": "StrategyPayload",
        "watcher_object.version": "1.0",
        "watcher_object.namespace": "watcher"
      },
      "created_at": "2016-11-04T16:29:20Z",
      "uuid": "4a97b9dd-2023-43dc-b713-815bdd94d4d6"
    },
    "watcher_object.name": "AuditActionPayload",
    "watcher_object.version": "1.0",
    "watcher_object.namespace": "watcher"
  },
  "publisher_id": "infra-optim:localhost",
  "timestamp": "2016-11-04 16:31:36.264673   ",
  "event_type": "audit.strategy.end",
  "message_id": "cbcf9f2c-7c53-4b4d-91ec-db49cca024b6"
}

audit.strategy.error

{
  "priority": "ERROR",
  "payload": {
    "watcher_object.data": {
      "audit_type": "ONESHOT",
      "parameters": {
        "para2": "hello",
        "para1": 3.2
      },
      "state": "ONGOING",
      "updated_at": null,
      "deleted_at": null,
      "fault": {
        "watcher_object.data": {
          "exception": "WatcherException",
          "exception_message": "TEST",
          "function_name": "test_send_audit_action_with_error",
          "module_name": "watcher.tests.notifications.test_audit_notification"
        },
        "watcher_object.name": "ExceptionPayload",
        "watcher_object.namespace": "watcher",
        "watcher_object.version": "1.0"
      },
      "goal": {
        "watcher_object.data": {
          "uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
          "name": "dummy",
          "updated_at": null,
          "deleted_at": null,
          "efficacy_specification": [],
          "created_at": "2016-11-04T16:25:35Z",
          "display_name": "Dummy goal"
        },
        "watcher_object.name": "GoalPayload",
        "watcher_object.version": "1.0",
        "watcher_object.namespace": "watcher"
      },
      "interval": null,
      "scope": [],
      "strategy": {
        "watcher_object.data": {
          "parameters_spec": {
            "properties": {
              "para2": {
                "type": "string",
                "default": "hello",
                "description": "string parameter example"
              },
              "para1": {
                "description": "number parameter example",
                "maximum": 10.2,
                "type": "number",
                "default": 3.2,
                "minimum": 1.0
              }
            }
          },
          "name": "dummy",
          "uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
          "updated_at": null,
          "deleted_at": null,
          "created_at": "2016-11-04T16:25:35Z",
          "display_name": "Dummy strategy"
        },
        "watcher_object.name": "StrategyPayload",
        "watcher_object.version": "1.0",
        "watcher_object.namespace": "watcher"
      },
      "created_at": "2016-11-04T16:29:20Z",
      "uuid": "4a97b9dd-2023-43dc-b713-815bdd94d4d6"
    },
    "watcher_object.name": "AuditActionPayload",
    "watcher_object.version": "1.0",
    "watcher_object.namespace": "watcher"
  },
  "publisher_id": "infra-optim:localhost",
  "timestamp": "2016-11-04 16:31:36.264673   ",
  "event_type": "audit.strategy.error",
  "message_id": "cbcf9f2c-7c53-4b4d-91ec-db49cca024b6"
}

audit.planner.start

{
  "priority": "INFO",
  "payload": {
    "watcher_object.data": {
      "audit_type": "ONESHOT",
      "parameters": {
        "para2": "hello",
        "para1": 3.2
      },
      "state": "ONGOING",
      "updated_at": null,
      "deleted_at": null,
      "fault": null,
      "goal": {
        "watcher_object.data": {
          "uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
          "name": "dummy",
          "updated_at": null,
          "deleted_at": null,
          "efficacy_specification": [],
          "created_at": "2016-11-04T16:25:35Z",
          "display_name": "Dummy goal"
        },
        "watcher_object.name": "GoalPayload",
        "watcher_object.version": "1.0",
        "watcher_object.namespace": "watcher"
      },
      "interval": null,
      "scope": [],
      "strategy": {
        "watcher_object.data": {
          "parameters_spec": {
            "properties": {
              "para2": {
                "type": "string",
                "default": "hello",
                "description": "string parameter example"
              },
              "para1": {
                "description": "number parameter example",
                "maximum": 10.2,
                "type": "number",
                "default": 3.2,
                "minimum": 1.0
              }
            }
          },
          "name": "dummy",
          "uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
          "updated_at": null,
          "deleted_at": null,
          "created_at": "2016-11-04T16:25:35Z",
          "display_name": "Dummy strategy"
        },
        "watcher_object.name": "StrategyPayload",
        "watcher_object.version": "1.0",
        "watcher_object.namespace": "watcher"
      },
      "created_at": "2016-11-04T16:29:20Z",
      "uuid": "4a97b9dd-2023-43dc-b713-815bdd94d4d6"
    },
    "watcher_object.name": "AuditActionPayload",
    "watcher_object.version": "1.0",
    "watcher_object.namespace": "watcher"
  },
  "publisher_id": "infra-optim:localhost",
  "timestamp": "2016-11-04 16:31:36.264673   ",
  "event_type": "audit.planner.start",
  "message_id": "cbcf9f2c-7c53-4b4d-91ec-db49cca024b6"
}

audit.planner.end

{
  "priority": "INFO",
  "payload": {
    "watcher_object.data": {
      "audit_type": "ONESHOT",
      "parameters": {
        "para2": "hello",
        "para1": 3.2
      },
      "state": "ONGOING",
      "updated_at": null,
      "deleted_at": null,
      "fault": null,
      "goal": {
        "watcher_object.data": {
          "uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
          "name": "dummy",
          "updated_at": null,
          "deleted_at": null,
          "efficacy_specification": [],
          "created_at": "2016-11-04T16:25:35Z",
          "display_name": "Dummy goal"
        },
        "watcher_object.name": "GoalPayload",
        "watcher_object.version": "1.0",
        "watcher_object.namespace": "watcher"
      },
      "interval": null,
      "scope": [],
      "strategy": {
        "watcher_object.data": {
          "parameters_spec": {
            "properties": {
              "para2": {
                "type": "string",
                "default": "hello",
                "description": "string parameter example"
              },
              "para1": {
                "description": "number parameter example",
                "maximum": 10.2,
                "type": "number",
                "default": 3.2,
                "minimum": 1.0
              }
            }
          },
          "name": "dummy",
          "uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
          "updated_at": null,
          "deleted_at": null,
          "created_at": "2016-11-04T16:25:35Z",
          "display_name": "Dummy strategy"
        },
        "watcher_object.name": "StrategyPayload",
        "watcher_object.version": "1.0",
        "watcher_object.namespace": "watcher"
      },
      "created_at": "2016-11-04T16:29:20Z",
      "uuid": "4a97b9dd-2023-43dc-b713-815bdd94d4d6"
    },
    "watcher_object.name": "AuditActionPayload",
    "watcher_object.version": "1.0",
    "watcher_object.namespace": "watcher"
  },
  "publisher_id": "infra-optim:localhost",
  "timestamp": "2016-11-04 16:31:36.264673   ",
  "event_type": "audit.planner.end",
  "message_id": "cbcf9f2c-7c53-4b4d-91ec-db49cca024b6"
}

audit.planner.error

{
  "priority": "ERROR",
  "payload": {
    "watcher_object.data": {
      "audit_type": "ONESHOT",
      "parameters": {
        "para2": "hello",
        "para1": 3.2
      },
      "state": "ONGOING",
      "updated_at": null,
      "deleted_at": null,
      "fault": {
        "watcher_object.data": {
          "exception": "WatcherException",
          "exception_message": "TEST",
          "function_name": "test_send_audit_action_with_error",
          "module_name": "watcher.tests.notifications.test_audit_notification"
        },
        "watcher_object.name": "ExceptionPayload",
        "watcher_object.namespace": "watcher",
        "watcher_object.version": "1.0"
      },
      "goal": {
        "watcher_object.data": {
          "uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
          "name": "dummy",
          "updated_at": null,
          "deleted_at": null,
          "efficacy_specification": [],
          "created_at": "2016-11-04T16:25:35Z",
          "display_name": "Dummy goal"
        },
        "watcher_object.name": "GoalPayload",
        "watcher_object.version": "1.0",
        "watcher_object.namespace": "watcher"
      },
      "interval": null,
      "scope": [],
      "strategy": {
        "watcher_object.data": {
          "parameters_spec": {
            "properties": {
              "para2": {
                "type": "string",
                "default": "hello",
                "description": "string parameter example"
              },
              "para1": {
                "description": "number parameter example",
                "maximum": 10.2,
                "type": "number",
                "default": 3.2,
                "minimum": 1.0
              }
            }
          },
          "name": "dummy",
          "uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
          "updated_at": null,
          "deleted_at": null,
          "created_at": "2016-11-04T16:25:35Z",
          "display_name": "Dummy strategy"
        },
        "watcher_object.name": "StrategyPayload",
        "watcher_object.version": "1.0",
        "watcher_object.namespace": "watcher"
      },
      "created_at": "2016-11-04T16:29:20Z",
      "uuid": "4a97b9dd-2023-43dc-b713-815bdd94d4d6"
    },
    "watcher_object.name": "AuditActionPayload",
    "watcher_object.version": "1.0",
    "watcher_object.namespace": "watcher"
  },
  "publisher_id": "infra-optim:localhost",
  "timestamp": "2016-11-04 16:31:36.264673   ",
  "event_type": "audit.planner.error",
  "message_id": "cbcf9f2c-7c53-4b4d-91ec-db49cca024b6"
}

备选方案

与其使用版本化对象,我们可以定义审计通知的有效负载,而无需任何版本支持。

数据模型影响

将创建新的版本化对象,但它们都不会被持久化,因为它们将用于构建通知的内容。

以下是一些需要声明的有效负载

@base.WatcherObjectRegistry.register_notification
class AuditPayload(notificationbase.NotificationPayloadBase):

    VERSION = '1.0'

    fields = {
        'uuid': fields.UUIDField(),
        'audit_type': fields.StringField(),
        'state': fields.StringField(),
        'parameters': fields.FlexibleDictField(nullable=True),
        'interval': fields.IntegerField(nullable=True),
        'goal_uuid': fields.UUIDField(),
        'strategy_uuid': fields.UUIDField(nullable=True),
        'goal': fields.ObjectField('Goal'),
        'strategy': fields.ObjectField('Strategy', nullable=True),
        'created_at': fields.DateTimeField(nullable=True),
        'updated_at': fields.DateTimeField(nullable=True),
        'deleted_at': fields.DateTimeField(nullable=True),
    }


@base.WatcherObjectRegistry.register_notification
class AuditStateUpdatePayload(notificationbase.NotificationPayloadBase):

    VERSION = '1.0'

    fields = {
        'old_state': fields.StringField(nullable=True),
        'state': fields.StringField(nullable=True),
    }


@base.WatcherObjectRegistry.register_notification
class AuditUpdatePayload(AuditPayload):

    VERSION = '1.0'

    fields = {
        'state_update': fields.ObjectField('AuditStateUpdatePayload'),
    }

REST API 影响

无。

安全影响

无。

通知影响

此蓝图将实现以下通知

  • audit.create

  • audit.update

  • audit.delete

  • audit.strategy.start

  • audit.strategy.end

  • audit.strategy.error

  • audit.planner.start

  • audit.planner.end

  • audit.planner.error

其他最终用户影响

无。

性能影响

启用后,每次发生触发通知的事件时,都会调用发送通知的代码。这对于 Watcher 本身来说问题不大,但应考虑所使用的消息总线上的负载。

其他部署者影响

为了发出通知,部署者将不得不使用 oslo.messaging 配置通知主题。通过 oslo.messaging 暴露的其他配置选项也可以进行调整。

开发人员影响

开发者应遵守适当的版本化指南,并在创建/更新通知时使用通知基类。

实现

负责人

主要负责人

vincent-francoise

工作项

  • 实施 audit.create

  • 实施 audit.update

  • 实施 audit.delete

  • 实施 audit.strategy.start

  • 实施 audit.strategy.end

  • 实施 audit.strategy.error

  • 实施 audit.planner.start

  • 实施 audit.planner.end

  • 实施 audit.planner.error

依赖项

测试

这些通知主要需要通过单元测试进行测试。

文档影响

应提供一个通知示例,并使其在在线文档中动态可用。

Watcher 架构 中的序列图。

参考资料

无。