插件¶
OpenStack 生态系统非常广泛且不断发展。DevStack 的价值在于它足够简单,可以清楚地理解其运作方式。但同时我们也希望尽可能地支持 OpenStack 生态系统。我们通过插件来实现这一点。
DevStack 插件是位于 DevStack 树之外的 bash 代码片段。它们通过严格的契约进行调用,因此这些插件可以确信,随着 DevStack 的发展,它们将继续工作。
先决条件¶
如果您计划创建一个将在服务目录中托管服务的插件(也就是说,您的插件将使用 get_or_create_service 命令),请确保您申请 服务类型权限 以保留有效的服务类型。这将有助于确保您服务的部署都使用相同的服务类型。
插件接口¶
DevStack 支持一种标准机制,用于从外部仓库包含插件。插件接口假定以下内容
一个外部 git 仓库,其中包含一个顶层目录 devstack/。在该目录中可以有 3 个文件。
override-defaults- 一个包含全局变量的文件,这些变量将在 lib/* 文件之前被读取。这允许插件覆盖 lib/* 文件中设置的默认值。例如,override-defaults 可以导出 CINDER_ENABLED_BACKENDS 以包含插件特定的存储后端,从而能够覆盖 Cinder 的默认仅 lvm 存储后端。
settings- 一个包含全局变量的文件,这些变量将在流程的早期被读取。如果其他插件可能依赖于此插件,并且需要访问全局变量来完成其工作,这将很有帮助。您的设置应包含插件所需的任何
enable_service行。如果使用run_process启动服务,这一点尤其重要,因为它仅适用于已启用的服务。请小心允许用户覆盖全局变量以自定义其环境。通常,最好仅在变量未设置或为空时提供默认值;例如,在 bash 语法中
FOO=${FOO:-default}。该文件应包含一个
define_plugin行,以指示插件的名称,该名称是用户在“enable_plugin”行中应使用的名称。通常,它应该是 git 仓库路径的最后一个组件(例如,如果插件的仓库是 openstack/foo,那么这里的名称应该是“foo”)define_plugin <YOUR PLUGIN>
如果您的插件依赖于另一个插件,请在此文件中使用如下行指示它
plugin_requires <YOUR PLUGIN> <OTHER PLUGIN>
对于完整的示例,如果插件“foo”依赖于“bar”,则
settings文件应包含define_plugin foo plugin_requires foo bar
Devstack 目前不使用此依赖信息,因此重要的是用户继续在
local.conf中以正确的顺序添加 enable_plugin 行,但是添加此信息允许其他工具在自动生成local.conf文件时考虑依赖信息。plugin.sh- 实际的插件。它由 devstack 在stack.sh运行期间定义的特定点执行。插件.sh 的内部结构如下所述。
插件通过将以下内容添加到 local.conf 的 localrc 部分来注册。
它们以以下格式添加
[[local|localrc]]
enable_plugin <NAME> <GITURL> [GITREF]
name- 一个任意名称。(例如:glusterfs、docker、zaqar、congress)giturl- 一个有效的 git url,可以克隆gitref- 一个可选的 git ref(分支/ref/tag),将被克隆。默认值为 master。
一个例子如下
enable_plugin ec2-api https://opendev.org/openstack/ec2-api
plugin.sh 契约¶
plugin.sh 是一个 bash 脚本,它将在 stack.sh、unstack.sh 和 clean.sh 期间的特定点被调用。它将以以下方式被调用
source $PATH/TO/plugin.sh <mode> [phase]
mode 可以被认为是正在调用的主要模式,当前是:stack、unstack、clean。 phase 由具有多个点在其运行期间需要能够执行代码的模式使用。所有现有的 mode 和 phase 点都被认为是 强契约,不会在没有合理的弃用期的情况下被删除。如果我们需要它们来支持 devstack 中的其他类型的插件,可以随时添加新的 mode 或 phase 点。
当前完整的 mode 和 phase 列表是
stack - 由
stack.sh在其运行的不同阶段调用四次pre-install - 在系统(OS)设置完成后,在安装项目源代码之前调用。
install - 在安装了第 1 层和第 2 层项目的源代码及其依赖项之后调用。
post-config - 在配置了第 1 层和第 2 层服务之后调用。此时应该存在已启用服务的所有配置文件。
extra - 在第 1 层和第 2 层服务启动后,在结尾附近调用。
test-config - 在 devstack 结尾被调用,用于配置 tempest 或任何其他测试环境
unstack - 由
unstack.sh在关闭其他服务之前调用。clean - 由
clean.sh在清理其他服务之前调用,但在调用unstack.sh之后。
示例插件¶
一个示例插件如下所示。
devstack/settings:
# settings file for template
enable_service template
devstack/plugin.sh:
# plugin.sh - DevStack plugin.sh dispatch script template
function install_template {
...
}
function init_template {
...
}
function configure_template {
...
}
# check for service enabled
if is_service_enabled template; then
if [[ "$1" == "stack" && "$2" == "pre-install" ]]; then
# Set up system services
echo_summary "Configuring system services Template"
install_package cowsay
elif [[ "$1" == "stack" && "$2" == "install" ]]; then
# Perform installation of service source
echo_summary "Installing Template"
install_template
elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
# Configure after the other layer 1 and 2 services have been configured
echo_summary "Configuring Template"
configure_template
elif [[ "$1" == "stack" && "$2" == "extra" ]]; then
# Initialize and start the template service
echo_summary "Initializing Template"
init_template
fi
if [[ "$1" == "unstack" ]]; then
# Shut down template services
# no-op
:
fi
if [[ "$1" == "clean" ]]; then
# Remove state and transient data
# Remember clean.sh first calls unstack.sh
# no-op
:
fi
fi
插件执行顺序¶
插件在上述阶段的树内服务之后运行。例如,如果您需要在 Keystone 启动之前发生某些事情,您应该在 post-config 阶段执行此操作。
可以在您的 local.conf 中指定多个插件。当发生这种情况时,插件将在每个阶段以 顺序 执行。这允许插件通过记录用户必须声明它们的顺序来概念性地相互依赖。正式的依赖机制超出了当前工作的范围。
系统包¶
基于 Devstack¶
Devstack 提供了一个自定义框架,用于在执行的早期阶段获取已安装的包。这些包可以定义为插件中的文件,这些文件包含换行符分隔的插件所需的包列表
支持的打包系统包括 apt 和 dnf,跨多个发行版。要启用插件以连接到此并安装软件包依赖项,可以在插件仓库的顶层列出软件包,如下所示
./devstack/files/debs/$plugin_name- 在 Ubuntu 或 Debian 上运行时要安装的软件包。./devstack/files/rpms/$plugin_name- 在 Red Hat、Fedora 或 CentOS 上运行时要安装的软件包。
虽然没有计划删除这种安装软件包的方法,但插件应将其视为已弃用,以支持下面描述的 bindep 支持。
bindep¶
该 bindep 项目已成为 OpenStack 项目指定二进制依赖项的事实标准。
插件可以提供一个 ./devstack/files/bindep.txt 文件,该文件将使用 默认 配置文件安装软件包。有关语法等,请参阅 bindep 文档。
也可以使用 bindep.txt 通过安装函数中提供的 -bindep 标志从源代码安装的项目。例如
if use_library_from_git "diskimage-builder"; then
GITREPO["diskimage-builder"]=$DISKIMAGE_BUILDER_REPO_URL
GITDIR["diskimage-builder"]=$DEST/diskimage-builder
GITBRANCH["diskimage-builder"]=$DISKIMAGE_BUILDER_REPO_REF
git_clone_by_name "diskimage-builder"
setup_dev_lib -bindep "diskimage-builder"
fi
将导致 bindep.txt 的 diskimage-builder 项目所需的任何软件包被安装。但是,在源安装和发布/pypi 安装之间切换项目(例如,使用 foo-dsvm 和 foo-dsvm-src 测试以涵盖发布依赖项和主版本)的任务将必须处理 bindep.txt 在没有源代码目录的情况下不可用。
在 OpenStack Gate 中使用插件¶
对于日常使用,DevStack 插件可以存在于互联网上可访问的任何 git 树中。但是,当在 OpenStack gate 中使用 DevStack 插件时,它们必须位于 OpenStack 的 gerrit 中的项目中。这允许测试插件,并提供与上游 git 仓库故障隔离(我们经常看到足以成为问题的故障)。
理想情况下,插件将包含在正在测试的项目的 devstack 目录中。例如,openstack/ec2-api 项目在其自己的树中支持其插件。
但是,有时 DevStack 插件可能仅用于配置将由 OpenStack 的其余部分使用的后端服务,因此没有“项目树”。好的示例包括:集成后端存储(例如 ceph 或 glusterfs)、集成 SDN 控制器(例如 ovn、OpenDayLight)或集成替代 RPC 系统(例如 zmq、qpid)。在这些情况下,最佳实践是构建一个专用的 openstack/devstack-plugin-FOO 项目。
旧版 project-config 作业¶
要启用插件在 gate 作业中使用,需要在 project-config 中的 jenkins/jobs/<project>.yaml 定义中需要以下行
# Because we are testing a non standard project, add the
# our project repository. This makes zuul do the right
# reference magic for testing changes.
export PROJECTS="openstack/ec2-api $PROJECTS"
# note the actual url here is somewhat irrelevant because it
# caches in nodepool, however make it a valid url for
# documentation purposes.
export DEVSTACK_LOCAL_CONFIG="enable_plugin ec2-api https://opendev.org/openstack/ec2-api"
Zuul v3 作业¶
请参阅 将 Zuul V2 CI 作业迁移到 V3 中的 devstack_plugins 示例。
参见¶
有关 devstack 插件的更多灵感,您可以查看 插件注册表。