Murano/简化元数据仓库
目录
范围
本文档定义了 Murano 元数据仓库的简化(初始)版本的职能需求,并提供了一些设计和实现建议。
目的
Murano 元数据仓库的简化(初始)版本将用于操作(存储、显示、分组和用于部署)当前格式(所谓的“Murano vCurrent”)的元数据对象 - 不包含服务依赖关系、继承、聚合和大多数其他特定于服务的数据。目的是创建尽可能简单的元数据对象存储,而无需对现有的 Murano 组件进行任何重大修改。但是,这个简单的仓库将作为未来修改和重构的起点 - 最终将导致一个高级的、由元数据驱动的互操作服务目录(所谓的“Murano vNext”)
元数据对象结构
目前,Murano Conductor 使用 5 种类型的元数据对象
- 工作流程
- Heat 模板
- Agent 模板
- Agent 配置模板
- Powershell 脚本
此外,还有 Murano Dashboard 使用的 UI 定义。建议添加一种新的元数据类型(“服务清单”),它将把所有其他类型的元数据对象与给定的服务绑定在一起,并由元数据服务用于构建服务目录。所有元数据对象都应存储在元数据仓库中,按类型分组,维护嵌套的、类似目录的结构(每种类型的所有文件都应进入同一个目录)。目录结构应根据下表定义
服务清单
这是为了支持服务目录功能而提出的新的元数据对象。在元数据仓库的第一个版本中,它将仅定义服务的几个基本属性,但将来会发生重大变化,最终定义服务及其在 Murano 生态系统中的位置。它还通过定义所需的文件名称将所有其他类型的元数据对象绑定在一起,从而允许轻松列出和检索单个服务的依赖项。清单应定义为 YAML 文件,包含以下属性
- 清单版本 - 元数据格式的版本,指示如何解释所有其他字段。这是唯一字段。元数据仓库的首次实现(根据本文档实现)应将其设置为 0.1。所有后续格式修改都应增加此值。预计当我们考虑实现 Murano vNext 时,清单应具有版本 1.0
- 服务显示名称 - 目前,这与 Dynamic UI 的“name”属性重复。将来,我们将从那里删除它。在第一个版本中,让我们保持重复:UI 文件中的名称将用于在“新建服务”对话框中显示服务名称,清单中的名称将用于在元数据仓库的 UI 中列出服务。
- 描述 - 目前,这与 Dynamic UI 的“description”属性重复。将来,我们将从那里删除它。在第一个版本中,让我们保持重复:UI 文件中的描述将用于在“新建服务”对话框中显示服务描述,清单中的描述将用于在元数据仓库的 UI 中列出服务。
- 完全限定的服务名称 - 完整的服务名称,旨在全局唯一。目前,这应与 Dynamic UI 的“type”属性重复。将来,我们将从那里删除它,并在清单中以反向基于域的形式,例如 com.mirantis.murano.windows.activedirectory
- 作者 - 服务定义的作者姓名。仅用于在元数据仓库 UI 中显示的信息
- 版本 - 服务定义的版本。仅用于在元数据仓库 UI 中显示的信息
- 启用 - 布尔字段,允许云管理员禁止使用此服务定义。具有此属性等于 False 的服务将存在于元数据仓库中,但该服务将不可在 Murano Dashboard 的“新建服务”对话框中选择。
- UI 表单 - 定义此服务用户界面的 UI 定义文件的文件名列表。在第一个版本中,由于当前 DynamicUI 设计的限制,每个服务始终包含单个文件。所有表单(步骤)都将从此文件加载。
在未来的修订版本中,此属性将包含一个有序的表单列表(以某种格式,例如 filename:formname),因此单个 UI 可以从多个共享文件加载。
- 工作流 - 此服务的工作流定义文件的文件名列表。
- Heat 模板 - 此服务的热模板文件的文件名列表。
- Agent 模板 - 此服务的主机模板文件的文件名列表。
脚本 - 此服务的 powershell 脚本的文件名列表。
在工作流、Heat 模板、Agent 模板和脚本中引用的所有文件都应具有相对于适当目录的相对文件路径(参见上表)。例如,名为 “AD.xml” 的工作流将在 “data/workflows/AD.xml” 中查找,名为 “SqlServerCluster/FailoverCluster.template” 的 Agent 模板将在 “data/templates/agent/SqlServerCluster/FailoverCluster.template” 中查找。“..” 在文件名中被禁止,因此搜索不应在给定元数据对象类型的根目录之外的目录中进行。如果元数据仓库中缺少这些部分中提到的任何文件,则服务定义将被视为无效,并且不能在 Dashboard 或 Conductor 中使用。
元数据查询 API
元数据仓库将为 Murano 组件(在第一个版本中 - 仅为 Conductor 和 Dashboard)提供一个 RESTful API 端点,以便它们可以充当元数据仓库的客户端并查询所需的元数据对象。将提供两个主要的 API
- 获取所有活动服务的 UI 描述
此调用将由 Murano Dashboard 进行。作为响应,元数据仓库将检查所有服务清单文件,处理它们并收集提及的服务中“enabled”属性设置为 true 的所有 UI 定义的文件名。然后,仓库将创建一个包含所有这些文件(保留目录结构)的 tar.gz 存档,并将存档放入响应流中。
- 获取所有活动服务的 Conductor 元数据
此调用将由 Conductor 进行。作为响应,元数据仓库将检查所有服务清单文件,处理它们并收集提及的服务中“enabled”属性设置为 true 的所有工作流定义、Heat 模板、Agent 模板和脚本的文件名。然后,仓库将创建一个包含所有这些文件(保留目录结构)的 tar.gz 存档,并将存档放入响应流中。
在处理这些调用的服务时,仓库应以服务驱动的方式运行,按照以下算法
- 迭代 data/services 目录中的文件,打开所有清单文件,解析它们,处理(如果需要,根据清单版本进行过滤)其内容,检查“enabled”标志。
- 对于每个启用的服务,创建一个单独的引用文件名列表
- 对于每个列表中的每个文件名,验证该文件是否存在于仓库中。如果至少缺少一个文件,则清空与此服务对应的整个列表。
- 将非空文件列表合并到一个文件名集合中(无重复项)
- 从此文件名集合构建结果存档
例如,假设仓库中有 3 个启用的服务:Service1、Service2、Service3。Service1 引用文件 A、B、C Service2 引用文件 C、D Service3 引用文件 D、E 假设文件 B 缺少在仓库中。在这种情况下,结果存档应包含文件 C、D、E
服务器端缓存
当元数据仓库为上述 API 中的任何一个创建 tar.gz 存档时,它可以保留结果文件。所有后续的相同 API 调用都可以立即返回相同的文件,而无需重新创建存档。该文件保留到仓库被任何管理操作(如下所示)修改为止 - 在这种情况下,缓存副本将被删除,任何后续 API 调用都将导致生成新的存档。
客户端缓存
元数据仓库的客户端(Murano Conductor 和 Murano Dashboard)也可以在本地存储收到的元数据存档的副本。当他们下次需要获取元数据时,他们可以计算现有副本的哈希和,并将其作为适当 API 调用的附加参数传递给仓库。在这种情况下,元数据仓库将匹配收到的哈希和与当前存档的哈希和(无论是服务器端存储的副本,还是新生成的存档(如果副本不存在))。如果哈希和匹配(这意味着客户端拥有最新的元数据副本),API 调用应返回 HTTP 304(未修改)状态码,这将通知客户端它可以重用其缓存的元数据副本。如果哈希和不同,元数据仓库将返回带有 HTTP 响应的存档(并且在这种情况下,HTTP 返回码应为 200),以便客户端可以更新其本地副本。
元数据管理操作
元数据仓库将提供管理 API 以允许修改元数据文件。这些 API 将按元数据类型分组,并提供基本的文件操作:上传新文件、删除现有文件、创建子目录、删除目录。
所有修改仓库的操作都将与元数据查询 API 调用正确同步(即,存档创建的查询正在进行中时,不应开始仓库的修改,反之亦然)
所有操作都将使元数据存档的适当服务器端缓存失效。这些缓存失效应该是独立的,即上传新的 UI 定义不应删除为 Conductor 创建的存档,上传与 Conductor 相关的文件不应删除为 Dashboard 创建的存档。上传服务清单应删除两个存档。
将提供一个只读 API 以通过路径获取任何给定的元数据文件。
服务目录操作
这是一个次要功能,因为它实际上复制了其他功能提供的功能,并且仅为了方便起见而需要。此外,此功能的适当实现可能需要数据库,而其他所有功能都可以在纯文件系统上完成。因此,建议将此部分的实现推迟到仓库的未来版本。由于此原因,此功能的规范可能会随着元数据格式可能已经更改而更改。
元数据仓库将提供与仓库中注册的服务列表一起使用的 API。将提供以下 API:列出所有服务返回注册到元数据仓库中的所有服务列表及其主要属性(显示名称、完全限定名称、描述、作者、版本)。
- 列出给定服务的元数据对象
- 返回给定服务的清单文件中引用的文件列表。服务由完全限定名称标识,文件伴有类型和相对于基于类型的目录的路径。输出足以让客户端使用上述第 8 节中描述的 API 获取文件的内容。
- 下载完整的服务定义。
- 返回一个包含服务清单文件及其引用的所有其他元数据文件的 tar.gz 存档。存档将根据文件类型保留目录结构
- 上传完整的服务定义。
- 上传包含某些服务的清单文件及其所有引用元数据文件在适当目录中的 tar.gz 存档。存档将被提取,文件将被放置到正确的目录中。
在共享文件的情况下(某些文件实际上是多个服务共有的),某些文件可能已经存在于目标目录中。在这种情况下,仅当文件的内容相同才能覆盖。否则,不会将任何内容添加到仓库中,并且上传将失败。
第 4p 中定义的 API 应符合与第 8p 中定义的 API 相同的规则:其使用应使所有缓存失效并与读取操作同步。
建议架构
元数据仓库将由仓库-api 组件(作为专用或共享 Linux 机器上的守护程序运行,并侦听预配置的 HTTP 端口)和 Web UI(作为 Horizon 的插件实现)组成。在开发的第一阶段,元数据将存储在纯文件系统中,而无需任何数据库。在未来的修改中,关系数据库可以被引入来存储清单数据,并且 MogoDB/MongoFS 可以被用于存储元数据对象。
API 定义
这些是正式的 API 定义。请参阅第 5、8 和 9 节,了解详细的 API 描述。API 应该遵循 RESTful 风格,基于 HTTP,使用标准的 HTTP 方法(get、put、post、delete),并返回标准的 HTTP 错误代码。所有 API 调用都应使用包含有效 Keystone token 的 X-Auth-Token HTTP header,该 token 用于标识用户、租户以及用户在租户中的角色。API 应该同时支持 HTTP 和 HTTPS。以下示例将针对 HTTP,使用“example.com”主机和 8080 端口给出。API 应该托管在主机上的“murano-repository”目录中。所有 API 都应通过 URL 进行版本控制。
获取 UI 定义
获取 Conductor 元数据
列出元数据对象
获取元数据对象
上传元数据对象
创建目录
删除元数据对象或目录
列出所有服务
稍后定义,详情请参阅 本章
列出给定服务的元数据对象
稍后定义,详情请参阅 本章
下载完整的服务定义
稍后定义,详情请参阅 本章
上传完整的服务定义
稍后定义,详情请参阅 本章
Web UI 描述
将使用 Horizon 应用程序为租户管理员提供修改元数据存储库所需的工具。它将允许浏览每种类型的元数据对象,以及服务列表,当第 9 节实现时。
基于角色的访问控制
实现 RBAC 的最简单方法是为每个租户提供隔离的元数据存储库。每个租户将创建一个独立的目录,其中将存储所有租户的文件,因此任何租户都无法访问其他租户的文件。通用的元数据对象(对应于随 Murano 捆绑的服务)应该存在于每个租户的目录中,但是应该通过简单地将内容从一些预配置的“dist”目录复制到新创建的存储库来完成。一旦内容被复制,所有进一步的修改都不会传播到租户的副本。复制应该在给定租户首次通过 API 访问存储库时发生。
按交付阶段划分的任务
初始 (PoC) 交付
- 证明概念并为 Conductor 提供存储库功能。仅添加客户端 API,即仅支持从存储库获取元数据的方式。我们将通过手动将文件放入文件系统(scp、ftp 或其他方式)将元数据放入存储库。
- 交付将分解为以下任务
- 用于在文件系统中操作元数据的核心服务,用于解析服务清单、创建归档等的服务。Conductor 的客户端 API
- Conductor 的修改,以从存储库获取元数据
支持 UI 定义
- 添加对存储动态 UI 定义的支持。
- 仍然没有简单的方法让用户上传自己的元数据 - 只能手动复制到文件系统
- 交付将分解为以下任务
- Dashboard 的 API 实现
- Dashboard 的修改,以从存储库获取 UI 定义
添加管理功能
- 此交付将允许用户轻松将新的元数据上传到存储库。
- 这可能是第一次公共交付 - 它可以被演示,因为它已经定义了元数据存储库所需的所有功能,至少在其基本状态下。
- 交付将分解为以下任务
- 实现管理 API
- 创建与管理 API 交互的 Web 界面
优化数据传输
- 此交付将通过添加缓存功能来提高元数据存储库的性能。
- 交付将分解为以下任务
- 服务器端缓存
- 客户端缓存
添加 RBAC
- 此交付将添加基于角色的访问控制,通过将不同租户的元数据存储隔离到不同的目录中。
实现与服务的批量操作
- 简单元数据存储库的最终计划交付将添加第 9 节中定义的 Service Catalog 功能。最有用的功能将是能够下载整个服务包(p9.3)并将该包上传到不同的存储库







