为 DevStack 贡献¶
概述¶
DevStack 使用 UNIX shell 脚本编写。它使用许多 bash 语法特性,因此仅限于 Bash(版本 4 及更高版本)和兼容的 shell。选择 shell 脚本是因为它最能说明设置和交互 OpenStack 组件的步骤。
DevStack 的官方仓库位于 opendev.org 的 https://opendev.org/openstack/devstack。除了跟踪 OpenStack 主干分支的 master 分支之外,还维护着一个单独的分支,用于所有 OpenStack 发布版本,从 Diablo 开始(stable/diablo)。
向 DevStack 贡献代码遵循通常的 OpenStack 流程,如 OpenStack wiki 中的 如何贡献 中所述。 DevStack 的 LaunchPad 项目 包含蓝图、错误等常规链接。
所有提交都使用 Gerrit 代码审查队列。
DevStack 中的主脚本是 stack.sh,它执行 DevStack 用例的大部分工作。有一个子脚本 functions 包含常用的 shell 函数,并被 DevStack 中的许多脚本使用。
可以在 tools 目录中找到许多其他脚本,这些脚本可能对支持 DevStack 安装很有用。特别是 info.sh 用于收集和报告有关已安装系统的信息,以及 install_prereqs.sh 用于处理 DevStack 的先决条件包的安装。例如,它可以用于预加载系统以创建快照。
仓库布局¶
DevStack 仓库通常将所有主脚本保存在根级别。
doc - 包含文档的 Sphinx 源代码。可以使用 tox -edocs 运行完整的文档构建。
extras.d - 包含由 stack.sh、unstack.sh 和 clean.sh 中的钩子调用的分派脚本。有关更多信息,请参阅 插件文档。
files - 包含各种丢失的文件,用于配置和操作 DevStack。这包括配置文件模板和系统依赖信息。如果需要,图像文件也会在此处下载和展开。
lib - 包含特定于每个项目的子脚本。这是管理项目服务的工作所在。每个顶级项目(Keystone、Nova 等)都在此处有一个文件。此外,还有一些用于系统服务和项目插件的脚本。这些变量和函数也由相关项目(如 Grenade)用于管理 DevStack 安装。
samples - 包含未包含在 DevStack 仓库中的本地文件的示例。
tests - DevStack 测试套件比较稀疏,主要由对 functions 和 functions-common 文件中特定脆弱函数的测试组成。
tools - 包含一组独立的脚本。虽然这些脚本可能会引用顶层 DevStack 配置,但通常可以单独运行。
脚本¶
DevStack 脚本通常应通过在 shebang 行中调用 env(1) 来开始
#!/usr/bin/env bash
有时脚本需要知道 DevStack 安装目录的位置。 TOP_DIR 应该始终指向那里,即使脚本本身位于子目录中
# Keep track of the current DevStack directory.
TOP_DIR=$(cd $(dirname "$0") && pwd)
许多脚本将利用来自 functions 文件的共享函数。还有 rc 文件(stackrc 和 openrc),通常会包含这些文件以设置用户环境的主要配置
# Keep track of the current DevStack directory.
TOP_DIR=$(cd $(dirname "$0") && pwd)
# Import common functions
source $TOP_DIR/functions
# Import configuration
source $TOP_DIR/openrc
stack.sh 是一个相当大的单片脚本,从头到尾流动。它已被分解为项目特定的子脚本(如上所述),位于 lib 中,以使 stack.sh 更易于管理并促进代码重用。
这些库子脚本具有许多固定的入口点,其中一些可能只是存根。这些入口点将按以下顺序由 stack.sh 调用
install_XXXX
configure_XXXX
init_XXXX
start_XXXX
stop_XXXX
cleanup_XXXX
在 lib/templates 中有一个子脚本模板,用于创建新的服务子脚本。用 <> 注释是描述如何使用模板的元注释,应将其删除。
为了显示项目函数执行的依赖关系和条件,应该在 stack.sh 中完成诸如 is_service_enabled 之类的顶级条件测试。子脚本中可能存在嵌套条件,例如在 configure_swift() 中测试 keystone 是否已启用。
stackrc¶
stackrc 是 DevStack 的全局配置文件。它负责调用 local.conf(或如果存在 localrc)以便识别本地用户配置。
什么属于 stackrc 的标准可以概括如下
直接在
stack.sh中处理的所有项目仓库和分支可以在
local.conf中引用的全局配置,即DEST、DATA_DIR全局服务配置,如
ENABLED_SERVICES由多个服务使用的变量,这些变量没有明确的所有者,例如
VOLUME_BACKING_FILE_SIZE(nova-compute 和 cinder)或PUBLIC_NETWORK_NAME(仅 neutron,但以前是 nova-network)。由于依赖顺序而无法在项目文件中干净地声明的变量,即更改项目文件源文件的顺序出于其他原因而无法更改,但较早的文件需要引用较晚文件中设置的变量。这种情况应该很少见。
此外,在引用 local.conf 之前在 stackrc 中声明的变量不允许覆盖(形式为 FOO=${FOO:-baz});如果可以,则它们已经可以在 local.conf 中更改,并且可以保留在项目文件中。
文档¶
DevStack 仓库现在包含 devstack.org 的所有静态页面,位于 doc/source 目录中。OpenStack CI 系统在每次提交后都会重建文档并更新 devstack.org(现在重定向到 https://docs.openstack.org/devstack/2025.2/)。
所有脚本都使用 shocco 进行处理,以使用注释呈现脚本,描述脚本下方。
因此,我们倾向于在代码上方的注释中略微冗长。Shocco 还支持注释中的 Markdown 格式;请谨慎使用。特别是,stack.sh 使用 Markdown 标题将脚本划分为逻辑部分。
用于驱动 <code>shocco</code> 的脚本是 <code>tools/build_docs.sh</code>。完整的文档构建也使用 <code>tox -edocs</code>,符合 OpenStack 项目标准。
Bash 风格指南¶
DevStack 定义了一组 bash 最佳实践,用于维护大量的 bash 脚本。这些应被视为审查过程的一部分。
DevStack 使用 bashate 风格检查器来强制执行基本指南,类似于 Python 的 pep8 和 flake8 工具。以下列表并不完整,bashate 检查的内容,也不是 bashate 检查的所有内容。所以很多代码行,时间太少。
空格规则¶
行不应包含尾随空格
文件中不应有硬制表符
缩进是 4 个空格,并且所有缩进都应该是它们的倍数
控制结构规则¶
then 应该与 if 在同一行
示例
if [[ -r $TOP_DIR/local.conf ]]; then
LRC=$(get_meta_section_files $TOP_DIR/local.conf local)
for lfile in $LRC; do
if [[ "$lfile" == "localrc" ]]; then
if [[ -r $TOP_DIR/localrc ]]; then
warn $LINENO "localrc and local.conf:[[local]] both exist, using localrc"
else
echo "# Generated file, do not edit" >$TOP_DIR/.localrc.auto
get_meta_section $TOP_DIR/local.conf local $lfile >>$TOP_DIR/.localrc.auto
fi
fi
done
fi
do 应该与 for 在同一行
变量和函数¶
应尽可能使用函数以提高清晰度
函数应尽可能使用
local变量以确保它们与其余环境隔离局部变量应为小写,全局变量应为大写
函数名称应_使用下划线,而不是驼峰式大小写。
函数应声明为正则表达式 ^function foo {$,代码从下一行开始
审查标准¶
在审查您的更改时,将遵循一些广泛的标准
是否通过测试 – 您的更改除非官方 CI 已成功对其运行,否则不会被彻底审查。
这是否属于 DevStack – DevStack 审查者有一个默认的“否”立场,但已准备好被您的更改说服。
对于非常大的更改,您应该考虑 插件系统,以查看您的代码是否更好地从主仓库中抽象出来。
对于较小的更改,您应该始终考虑是否可以将更改封装在
local.conf中的用户设置中。一个常见的例子是在ini文件中添加一个简单的配置选项。通常不需要为此添加特定标志,尽管添加关于如何实现更大目标(可能包括打开各种设置等)的文档始终受到欢迎。解决方法 – 有时会出现问题,DevStack 可以处于修复它们的位置。解决方法是可以的,但应在解决问题的根本原因的背景下呈现。这意味着它在代码和更改日志中进行了很好的注释,并且很可能包含指向修复底层问题的更改或错误的链接。
这是否应该上游 – DevStack 通常不会覆盖项目提供的默认选择,并尝试不要意外地修改行为。
提交消息中的上下文 – DevStack 涉及许多不同的领域,审查者需要有关更改的上下文才能做出良好的决策。我们还始终希望在现在甚至几年后,清楚我们为什么有动力进行更改。
进行更改、测试和 CI¶
DevStack 的更改由自动化持续集成作业进行测试,这些作业在各种 Linux 发行版上使用一些常见配置运行。这意味着 DevStack 的每一次更改都是自我测试的。这带来的一个主要好处是,开发人员通常不需要添加新的非投票测试作业来为 DevStack 添加功能。相反,可以添加功能,然后在 CI 中使用启用该功能的更改进行测试,一旦启用更改通过并且新行为得到沟通和记录,就可以合并该更改。
这个过程已被证明是有效的,并能更快地实现所需的功能。