跳转到: 导航, 搜索

Fuel/Plugins

Fuel Plugin SDK 指南位于 docs.openstack.org

本指南的最新版本已迁移至 https://docs.openstack.org/developer/fuel-docs/plugindocs/fuel-plugin-sdk-guide.html

此 wiki 页面仅供历史参考。

目录

可插拔架构是什么

从版本 6.0 开始,Fuel 具有在环境部署时安装插件的能力。Fuel 插件是可下载的软件组件,使您能够以灵活、可重复和可靠的方式向环境添加新功能。无需在 Fuel 部署云后手动安装驱动程序和补丁 - 插件会为您完成此操作。

Fuel 插件使您能够安装和配置云的附加功能,例如其他存储类型和网络功能。例如,负载均衡即服务 (LBaaS) 插件允许您将网络负载均衡功能添加到云中,以便将传入流量分配到多个节点。或者,您可能希望使用 GlusterFS 插件,以便将 Gluster 文件系统用作块存储 (Cinder) 的后端。

Fuel 提供了一个开源框架来创建这些插件,因此您可以启用 Fuel 在 OpenStack 云中添加的各种功能。如果您是创建驱动程序以使 OpenStack 与您的产品协同工作的硬件供应商,您可以创建一个插件,以便 Fuel 在启动新云时部署这些驱动程序。或者,您可能只是想启用 Fuel 中不易获得的 OpenStack 功能。由于 Fuel 包含一个可插拔框架,因此您不受“开箱即用”提供的功能的限制。

您还可以自由使用 DriverLog 作为所有 Fuel 插件的单一注册表。


架构限制

  • 核心功能 Fuel 插件只能在配置和部署环境之前安装。否则,您需要重新部署环境才能启用核心插件。应用程序级插件可以在已经部署的环境之上稍后安装。
  • Fuel 插件无法从一个主要版本升级到另一个主要版本。
  • Fuel 插件无法为 SDN 解决方案创建一个新的网络选项在 Fuel Web UI/UI 向导中。

6.1 功能

  • 插件以 RPM 格式提供
  • 插件支持从主要版本到次要版本的更新(1.0.0 到 1.0.1)

7.0 功能

8.0 功能

部署后安装插件

如果插件是应用程序级插件(可热插拔),例如 LMA 或 Zabbix,则在部署 OpenStack 环境后可以安装插件

  • 提供新的应用程序
  • 在新的节点上安装应用程序
  • 不会影响现有服务或应用程序
  • 不会覆盖现有任务


影响 Fuel 核心功能的插件,例如 SDN 或存储插件,只能在部署 OpenStack 环境之前安装。

应用程序级插件应在 metadata.yaml 文件中将“is_hotpluggable”属性设置为“true”。请参阅 metadata.yaml

环境仪表板中的插件链接和元数据

您可以通过 Puppet 清单请求 API,并注册非标准仪表板。

示例

  • absolute-dashboard-link.pp
notice('PLUGIN: fuel_plugin_example_v4/absolute-dashboard-link.pp')

$cluster_id = hiera('deployment_id')
$master_ip = hiera('master_ip')
$network_metadata = hiera_hash('network_metadata', {})
$os_public_vip = $network_metadata['vips']['public']['ipaddr']

$dashboard_name = 'Demo Plugin Dashboard #1'
$dashboard_desc = 'A Sample Absolute Dashboard Link'
$dashboard_link = "http://${os_public_vip}/dashboard"

$json_hash = { title       => $dashboard_name,
               description => $dashboard_desc,
               url         => $dashboard_link, }

$json_message = inline_template('<%= require "json"; JSON.dump(@json_hash) %>')

exec { 'create_dashboard_link':
  command => "/usr/bin/curl -H 'Content-Type: application/json' -X POST \
-d '${json_message}' \
http://${master_ip}:8000/api/clusters/${cluster_id}/plugin_links",
}

  • relative-dashboard-link.pp
notice('PLUGIN: fuel_plugin_example_v4/relative-dashboard-link.pp')

$cluster_id = hiera('deployment_id')
$master_ip = hiera('master_ip')

$dashboard_name = 'Demo Plugin Dashboard #2'
$dashboard_desc = 'A Sample Relative Dashboard Link'
$dashboard_link = "/dashboard"

$json_hash = { title       => $dashboard_name,
               description => $dashboard_desc,
               url         => $dashboard_link, }

$json_message = inline_template('<%= require "json"; JSON.dump(@json_hash) %>')

exec { 'create_dashboard_link':
  command => "/usr/bin/curl -H 'Content-Type: application/json' -X POST \
-d '${json_message}' \
http://${master_ip}:8000/api/clusters/${cluster_id}/plugin_links",
}

  • deployment_tasks.yaml
- id: fuel_plugin_example_v4
  type: group
  role: [fuel_plugin_example_v4]
  tasks:
    - hiera
    - globals
  required_for: [deploy_end]
  requires: [deploy_start]
  parameters:
    strategy:
      type: parallel

- id: fuel_plugin_example_v4-controller-deployment
  type: puppet
  groups: [primary-controller, controller]
  required_for: [connectivity_tests, deploy_end]
  requires: [netconfig, deploy_start]
  parameters:
    puppet_manifest: "deploy.pp"
    puppet_modules: "."
    timeout: 3600

- id: fuel_plugin_example_v4-deployment
  type: puppet
  groups: [fuel_plugin_example_v4]
  required_for: [deploy_end]
  requires: [deploy_start]
  parameters:
    puppet_manifest: "deploy.pp"
    puppet_modules: "."
    timeout: 3600
    retries: 10

- id: fuel_plugin_example_v4-post-deployment-sh
  type: shell
  role: [fuel_plugin_example_v4]
  required_for: [post_deployment_end]
  requires: [post_deployment_start]
  parameters:
    cmd: bash deploy.sh
    retries: 3
    interval: 20
    timeout: 180

- id: fuel_plugin_example_v4-absolute-dashboard-link
  type: puppet
  role: [fuel_plugin_example_v4]
  required_for: [post_deployment_end]
  requires: [post_deployment_start]
  parameters:
    puppet_manifest: "absolute-dashboard-link.pp"
    puppet_modules: "/etc/puppet/modules"
    timeout: 180

- id: fuel_plugin_example_v4-relative-dashboard-link
  type: puppet
  role: [fuel_plugin_example_v4]
  required_for: [post_deployment_end]
  requires: [post_deployment_start]
  parameters:
    puppet_manifest: "relative-dashboard-link.pp"
    puppet_modules: "/etc/puppet/modules"
    timeout: 180cluster_id}/plugin_links",
}

  • node_roles.yaml
fuel_plugin_example_v4:
  name: "Set here the name for the role. This name will be displayed in the Fuel web UI."
  description: "Write description for your role"
  has_primary: false                # whether has primary role or not
  public_ip_required: true          # whether requires public net or not
  weight: 100                       # weight that will be used for ordering on fuel ui
  • 将 API 添加到安装后任务的插件示例 — post_install.sh
#!/bin/sh

PLUGIN_NAME=fuel_plugin_example_v4
DASHBOARD_TITLE=Dashboard
DASHBOARD_DESC="A Sample Dashboard Link"
DASHBOARD_URL="/dashboard"

function obtain_token {

# Request a token for admin user
TENANT_NAME=admin
ADMIN_USERNAME=`python -c "import sys; import yaml; f = open('/etc/fuel/astute.yaml'); astute = yaml.load(f); print astute['FUEL_ACCESS']['user'];"`
ADMIN_PASSWORD=`python -c "import sys; import yaml; f = open('/etc/fuel/astute.yaml'); astute = yaml.load(f); print astute['FUEL_ACCESS']['password'];"`
TENANT_ID=admin

REQUEST="{\"auth\": {\"tenantName\":\"$TENANT_NAME\", \"passwordCredentials\": {\"username\": \"$ADMIN_USERNAME\", \"password\": \"$ADMIN_PASSWORD\"}}}"
RAW_TOKEN=`curl -s -d "$REQUEST" -H "Content-type: application/json" "https://:5000/v2.0/tokens"`
TOKEN=`echo $RAW_TOKEN | python -c "import sys; import json; response = json.loads(sys.stdin.read()); print response['access']['token']['id'];"`

}

function plugin_link {

which fuel > /dev/null
if [[ $? -eq 0 ]]; then

local num_retries=10
local i=0

while true; do
    # Fail if number of retries exeeded
    if [[ $i -gt $((num_retries + 1)) ]]; then
        # Report that plugin not registered
        echo "WARNING: Plugin failed to register before the timeout."
        echo "         Plugin dashboard link will not be added."
        return 1
    fi

    LAST_PLUGIN_ID=`fuel plugins -l | grep $PLUGIN_NAME | cut -d ' ' -f1`
    if [ "$LAST_PLUGIN_ID" != "" ]; then
        PLUGIN_ID=$LAST_PLUGIN_ID
        echo "Plugin ID is: $PLUGIN_ID"
        curl -H 'Content-Type: application/json' -H "X-Auth-Token: $TOKEN" -X POST -d \
"{\"title\":\"$DASHBOARD_TITLE\",\"description\":\"$DASHBOARD_DESC\",\"url\":\"$DASHBOARD_URL\"}" \
http://127.0.0.1:8000/api/v1/plugins/$PLUGIN_ID/links
        return 0
    fi

    sleep 1
    i=$((i++))
done
fi

}

obtain_token
echo $TOKEN

plugin_link &

组件兼容性注册表

组件注册表是 Fuel 中的组件兼容性机制。请参阅 蓝图

指定组件要求

考虑两个组件:组件 A 和组件 B。组件 A 需要组件 B 才能正常工作。

在 DSL 模型中,可以显式地描述这种关系

        - name: 'A'
            requires:
                - name: 'B'

DSL 模型可以在 Fuel openstack.yaml 文件中描述核心组件,在插件提供的 components.yaml 文件中描述。

在 Fuel Web UI 中,如果未选择组件 B,则将禁用组件 A 并显示相应的消息。

考虑三个组件:组件 A、组件 B 和组件 C。组件 A 需要组件 B 和组件 B 才能正常工作。

可以显式地描述这种关系

        - name: 'A'
            requires:
                - name: 'B'
                - name: 'C'
                message: 'C and B'

在这种情况下,只有在选择组件 B 和组件 C 时才能选择组件 A。

目前,对于组件 A 需要组件 B 或组件 C 或更多的情况,存在限制。

DVS 插件的要求示例

        - name: 'network:neutron:ml2:dvs'
          label: 'Neutron with VMware DVS'
          description: 'Neutron with VMware DVS ML2 plugin'
          requires:
            - name: 'network:neutron:core:ml2'
            - name: 'hypervisor:vmware'
            message: 'The VMware DVS plugin requires vCenter as the hypervisor option.'

指定组件兼容性

组件 A 与组件 B 的兼容性意味着组件 A 已与组件 B 进行了测试并证明可以正常工作。

DSL 模型示例

        - name: 'A'
            compatible:
                - name: 'B'
                - name: 'C'

如果在 Fuel Web UI 中选择组件 B 或组件 B,则组件 A 的 UI 表示形式将具有绿色工具提示。

指定组件不兼容性

组件 A 与组件 B 的不兼容性意味着组件 A 已与组件 B 进行了测试并证明无法正常工作。

DSL 模型示例

        - name: 'A'
            incompatible:
                - name: 'B'
                message: 'B incompatible with A'

选择组件 A 或组件 B 将在 Fuel Web UI 中禁用另一个组件。您只能选择组件 A 或组件 B,而不能同时选择两者。

具有未指定兼容性的组件

Fuel Web UI 会显示带有相应消息的灰色工具提示,用于具有未指定兼容性的组件。

设置选项卡插件分配

environment_config.yaml 文件中有一个“groups”属性,可用于分配插件。

插件可以形成任何组,也可以位于默认组之一:General(常规)、Security(安全)、Compute(计算)、Storage(存储)、Logging(日志记录)、OpenStack Services(OpenStack 服务)。如果您的插件使用自定义组名,则它将自动进入“Other(其他)”组。

请参阅 environment_config.yaml 模板


9.0 功能

  • 插件开发人员现在可以动态地将配置字段添加到他们的插件中。请参阅 蓝图
  • 改进了 Fuel 插件构建器。改进之处是修复了许多错误;没有新功能。有关如何安装最新版本的 Fuel 插件构建器,请参阅 #install_latest

如何为 Fuel 开发插件

规划为 Fuel 创建插件

入口开发要求

在计划为 Fuel 编写插件时,请注意以下建议

代码风格

Fuel Plugin 代码的可读性、可审查性和可维护性取决于使用标准编码风格,适用于 PuppetPython。强烈建议遵循这些风格指南。最佳方法是将代码风格检查器集成到您的 CI 流程中。以下是一些使用 puppet-lintpep8 的示例。

要安装这些检查器,请按照以下说明操作

  • Puppet
gem install puppet-lint
puppet-lint  --with-context ./myplugin/deployment_scripts
  • Python
pip install pep8
pep8 --show-source --show-pep8 ./myplugin/deployment_scripts

仓库

作为插件开发者,这是您创建插件的工作流程

  1. 您应该在您自己的、公开的仓库中开始插件开发。该仓库可以是任何公共 git 托管平台,例如 github。
  2. 当您准备将开发的插件项目放入 OpenStack 命名空间中的官方仓库时,您需要执行并确保以下操作
    • Fuel 团队 验证您的代码。
    • 您计划为插件设置 CI。
    • 确认您将支持多个版本的 Fuel。
    • 确认您正在以开源许可证发布您的插件代码。
    • 确认您的插件代码不包含二进制文件。
如何创建一个项目
  1. 请确保您已在以下资源中注册
    • LaunchPad。如果还没有,请参阅 官方 OpenStack 文档
    • review.openstack.org。开发人员需要被纳入核心和发布组。
  2. 在 Fuel 项目中请求创建仓库。进入 Launchpad 上的 Fuel 项目 并点击 Report a bug 链接。 Report-a-bug.png
  3. Summary 中,指定 Create a Fuel Plugin project in /OpenstackBug-report-sum.png
  4. Bug 描述应包括
    • 插件名称(例如,HA Fencing)
    • 插件功能概述(例如,在 HA 模式下启用基于 STONITH 的 fencing)
    • 开发者的联系信息(电子邮件、Skype 等) - 请确保核心组成员已在 review.openstack.org 上注册。否则,他们将无法被添加到核心成员中。
    • 包含联系信息的开发者列表(姓名、注册 review.openstack.org 的电子邮件)以进入核心审查员组 (示例) - 用于合并更改
    • 包含联系信息的开发者列表((姓名、注册 review.openstack.org 的电子邮件))以进入发布组 (示例) - 用于在仓库中创建发布分支和标签。您需要审查项目的提交,并确保进入核心和发布组的开发者列表都是正确的。
  5. 点击 Extra 选项。在菜单中,指定 devops 标签。 Bug-report-devops.png
  6. 在创建仓库后(这意味着您的 bug 应该被标记为 Fix CommittedFix Released),您可以开始将所需的文件填充到您的仓库中
    • 插件代码本身
    • 文档 - 请参阅 相应章节 以获取更多详细信息。
请求社区帮助进行代码审查

一旦您的代码准备好并上传到 /openstack 项目下的仓库中,您可以自由地请求 OpenStack 社区进行审查,以确保代码符合开发要求和 Fuel 插件框架的通用指南,如下所示。
这与 Gerrit 工作流 在 OpenStack 社区中使用一致。要请求审查,您可以进入 IRC 中的 #fuel-dev 频道。

Launchpad 项目

请考虑创建一个 Launchpad 项目,它将作为报告插件问题和跟踪开发进度的单一入口点。建议如下

  • 项目名称应类似于 fuel-plugin-<您的插件名称>
  • 项目创建过程是一个相当标准的过程,您可以在 官方 Launchpad 文档 中了解更多信息。
  • 项目页面应包含指向源插件仓库和 DriverLog 中条目的链接
  • 项目团队 应包含所有开发团队成员
  • 里程碑 应重复 metadata.yaml 文件中指定的插件版本(例如 1.0.0、2.0.0)

您可以在 此处 找到现有的 LP 项目列表。

使用标签和分支

为了更有效地跟踪发布周期,您可以使用

  • 发布分支
  • 标签

以下是这两个概念之间的区别

  • 标签表示分支在特定时间点的版本。
  • 分支表示与同一代码库上的其他开发工作并行运行的独立开发线程。分支上的更改最终可能会合并回另一个分支以统一它们。


建议您使用分支让最终用户构建您的插件。
为此,您需要

  • 创建一个相应的分支。
  • 编辑 README 文件以提供构建说明。有关更多详细信息,请参阅 相应章节


您还可以使用标签来跟踪单个分支内的进度。以下是两个示例

 Repo-tags-1.png
  Plugin-branch.png

分支命名约定

由于插件在 DriverLog 中发布,因此最终用户获取插件 RPM 的唯一方法是自行构建它。 因此,您应该考虑以下事项:

  • 分支名称应与兼容的 Fuel 版本一致。


参见

博客文章。


注意

  • 您应该在将所有必需的文件添加到仓库并检查后添加一个标签

它们是否包含版权。否则,您将需要创建新的标签。

  • 您应该使用控制台 gnupg 使用 gpg 密钥创建标签。 请确保它存在且未过期。


创建分支

有两种创建分支的方法

  • 从 CLI
git push <remote> <localref>:<remotebranch>

其中 <remote> 是您的 gerrit 远程的名称或完整的远程 URL,<localref> 是 refname(可以是分支或其他内容),<remotebranch> 是您要从中创建的分支的名称。

  • 从 Web UI
    1. 确保您是核心审查员。
    2. 进入 review.openstack.org。
    3. 在项目菜单中,点击分支。项目设置打开后,输入新的分支名称并点击创建分支按钮。请注意,“初始修订版”字段可以留空。

Plugin-create-branch-1.png.

删除分支

如果您想删除分支,您有两种不同的方法

  1. 通过邮件列表联系 openstack-infra 核心团队。请参阅 示例请求
  2. 在 Launchpad 的 Fuel 项目中报告一个 bug 并将其分配给 Fuel DevOps 团队。流程与 此处 描述的流程类似
  3. 在 freenode.net 上的 #openstack-infra IRC 频道中请求。您可以联系以下核心成员:fungi、clarkb、jeblair、pleia2。


请注意,无法手动删除分支。

CI

建议为您的 Fuel 插件设置 CI。以下部分提供了有关 CI 组件及其作用的摘要说明。

工具

以下是 Fuel 插件 CI 中使用的关键问题列表

CI 持续集成
CD 持续交付
OSTF OpenStack 测试框架
BVT 构建验证测试
JJB Jenkins Job Builder
VM 虚拟机
Fuel Fuel
Fuel CI Fuel CI
GitHub GitHub 服务器
Openstack Openstack
Gerrit OpenStack 审查工具

轻松构建自己的 CI https://github.com/openstack/fuel-plugin-ci

至于工具,以下工具正在使用中

  • 带有 Gerrit 代码审查工具的 GitHub 仓库
  • Jenkins CI 服务器 - 提供有关作业状态、调度程序、测试结果等的完整信息。
  • Jenkins Job Builder - 用于轻松添加和管理 Jenkins 作业的工具。它提供了一种以人类可读的 .yaml 标记语言存储作业配置并将它们转换为 Jenkins 特定的 .xml 的功能。
配置 Gerrit 集成的步骤
  1. 创建和配置 launchpad 用户以作为第三方开发者进行投票
  2. 在 Jenkins 中添加凭据(用户名、公钥)以进行 gerrit 插件配置
  3. 将电子邮件发送到 openstack-dev 邮件列表,提名您的系统以获取投票权限


准备开发和测试环境的步骤(必需)
  1. 应创建 OpenStack 和/或 Gerrit 仓库。有关更多详细信息,请参阅 仓库 部分。
  2. 应分配首选数量的测试实验室(插件特定)。
  3. 应安装和配置特定的硬件资源(插件特定)。
  4. 应配置测试实验室以设置环境和运行测试。请参阅 Fuel 开发文档
配置 CI 服务器的步骤(可选)
  1. 我们建议所有插件开发者都拥有自己的 CI 服务器。它提供了更好的版本控制、收集测试结果、删除重复作业、更轻松的配置和管理。
  2. 我们建议使用带有 Jenkins Job Builder 插件 的 Jenkins,它提供了易于作业管理和配置存储的功能。
  3. 我们建议从 git 安装 JJB 并从 以下部分 获取示例作业。您可能会发现主作业很有用:这应该是 plugins.yaml 和依赖的构建器:docs/builders/.sh。
  4. 我们建议创建一个 pre-commit 钩子来检查您的代码
#!/bin/bash
# Save this script to <PROJECT>/.git/hooks/pre-review and make it executable
set -e
set -o pipefail

find . -name '*.pp' | xargs -P1 -L1 puppet parser validate --verbose
find . -name '*.pp' | xargs -P1 -L1 puppet-lint \
          --fail-on-warnings \
          --with-context \
          --with-filename \
          --no-80chars-check \
          --no-variable_scope-check \
          --no-nested_classes_or_defines-check \
          --no-autoloader_layout-check \
          --no-class_inherits_from_params_class-check \
          --no-documentation-check \
          --no-arrow_alignment-check\
          --no-case_without_default-check
find . -name '*.erb' | xargs -P1 -L1 -I '%' erb -P -x -T '-' % | ruby -c
fpb --check  ./
示例作业
  • deploy-plugin.sh
#!/bin/bash
set -ex

export SYSTEM_TESTS="${WORKSPACE}/utils/jenkins/system_tests.sh"
export LOGS_DIR=${WORKSPACE}/logs/${BUILD_NUMBER}
export VENV_PATH='/home/jenkins/venv-nailgun-tests-2.9'
YOUR_PLUGIN_PATH="$(ls ./*rpm)" #Change this to appropriate fuel-qa variable for your plugin
export YOUR_PLUGIN_PATH         #

sh -x "${SYSTEM_TESTS}" -w "${WORKSPACE}" -V "${VENV_PATH}" -i "${ISO_PATH}" -t test -o --group="${TEST_GROUP}"
  • prepare_env.sh
#!/bin/bash

set -ex

export VENV_PATH="/home/jenkins/venv-nailgun-tests-2.9"

rm -rf "${VENV_PATH}"

REQS_PATH="${WORKSPACE}/fuel-qa/fuelweb_test/requirements.txt"

virtualenv --system-site-packages "${VENV_PATH}"
source "${VENV_PATH}/bin/activate"
pip install -r "${REQS_PATH}" --upgrade
django-admin.py syncdb --settings=devops.settings --noinput
django-admin.py migrate devops --settings=devops.settings --noinput
deactivate
  • syntax-build-plugin.sh
#!/bin/bash
set -ex

find . -name '*.erb' -print 0 | xargs -0 -P1 -I '%' erb -P -x -T '-' % | ruby -c
find . -name '*.pp' -print 0| xargs -0 -P1 puppet parser validate --verbose
find . -name '*.pp' -print 0| xargs -0 -P1 puppet-lint \
          --fail-on-warnings \
          --with-context \
          --with-filename \
          --no-80chars-check \
          --no-variable_scope-check \
          --no-nested_classes_or_defines-check \
          --no-autoloader_layout-check \
          --no-class_inherits_from_params_class-check \
          --no-documentation-check \
          --no-arrow_alignment-check

fpb --check  ./
fpb --build  ./
  • plugins.yaml
- project:
    name: plugin_name #Your plugin mame
    path_to_fuel_iso: $PWD #Path to FuelISO
    plugin_repo: plugin_repo #Your plugin repo name at stackforge
    email_to: emails_list #List of emails separated by comma
    test_group: test_group #Test group in fuel-qa for deployment tests of your plugin
    jobs:
      - 'prepare_env'
      - '{name}.build'
      - '{name}.{dist}.deploy':
          dist: 'centos'
      - '{name}.{dist}.deploy':
          dist: 'ubuntu'

- job-template:
    name: 'prepare_env'
    builders:
      - shell:
          !include-raw-escape './builders/prepare_env.sh'
    description: 'Prepare environment to testing'
    logrotate:
      numToKeep: 10
    parameters:
      - string:
          name: 'GERRIT_REFSPEC'
          default: 'refs/heads/master'
    scm:
      - git:
          branches:
            - $GERRIT_BRANCH
          refspec: $GERRIT_REFSPEC
          url: 'https://review.openstack.org/stackforge/fuel-qa'
          choosing-strategy: gerrit
          clean:
            before: true
    publishers:
      - email:
          notify-every-unstable-build: true
          recipients: '{email_to}'

- job-template:
    name: '{name}.build'
    builders:
      - shell:
          !include-raw-escape './builders/syntax-build-plugin.sh'
    description: '<a href=https://github.com/stackforge/{plugin_repo}>Build {name} plugin from fuel-plugins project</a>'
    logrotate:
      numToKeep: 10
    parameters:
      - string:
          name: 'GERRIT_REFSPEC'
          default: 'refs/heads/master'
    scm:
      - git:
          branches:
            - $GERRIT_BRANCH
          name: ''
          refspec: $GERRIT_REFSPEC
          url: 'https://review.openstack.org/stackforge/{plugin_repo}'
          choosing-strategy: gerrit
          clean:
            before: true
    triggers:
      - gerrit:
          trigger-on:
            - patchset-created-event #Trigger plugin build for every gerrit patchset
          projects:
            - project-compare-type: 'PLAIN'
              project-pattern: '{plugin_repo}'
              branches:
                - branch-compare-type: 'ANT'
                  branch-pattern: '**'
          silent: true
          server-name: 'review.openstack.org'
    publishers:
      - archive:
          artifacts: '*.rpm'
      - email:
          notify-every-unstable-build: true
          recipients: '{email_to}'

- job-template:
    name: '{name}.{dist}.deploy'
    builders:
      - copyartifact:
          project: '{name}.build'
          which-build: last-successful
      - inject:
          properties-content: |
            OPENSTACK_RELEASE={dist}
            TEST_GROUP={test_group}
            ISO_PATH={path_to_fuel_iso}
      - shell:
          !include-raw-escape './builders/deploy-plugin.sh'
    description: 'fuel-qa system test for {name}'
    logrotate:
      numToKeep: 10
    parameters:
      - string:
          name: 'GERRIT_REFSPEC'
          default: 'refs/heads/master'
    scm:
      - git:
          branches:
            - $GERRIT_BRANCH
          refspec: $GERRIT_REFSPEC
          url: 'https://review.openstack.org/stackforge/fuel-qa'
          choosing-strategy: gerrit
          clean:
            before: true
          wipe-workspace: false
    publishers:
      - archive:
          artifacts: 'logs/$BUILD_NUMBER/*'
      - email:
          notify-every-unstable-build: true
          recipients: '{email_to}'
CI/CD 工作流程

Cicdwf.png



就特定插件而言,我们建议您通过以下 CI 管道

  1. 准备实验室并启动或更新实验室(当构建了新的 Fuel ISO 时)
    • a) 从 Fuel CI 下载当前的 ISO。根据插件需求中指定的 Fuel 版本,Jenkins 下载发布的 ISO 和/或当前在核心 CI 上通过 BVT 测试的 ISO。(目前,这应该手动完成;将来,应提供 API 以通知外部 CI 关于新的稳定 ISO)。您还可以实现一个内部存储,以便在发布后下载最新的稳定 ISO。
    • b) 使用 fuel-devfuel-qa 仓库运行它,在控制台中部署此 ISO 并准备所需的实验室进行测试:$ fuel-main/utils/jenkins/system_tests -t test -j dis_fuelweb_test -i (下载的 Fuel-ISO 的路径) -o --group=setup -V ${VIRTUAL_ENV} -k 您可以在 Fuel 开发文档 中找到有关脚本安装和使用的所有信息
    • c) 从快照创建/还原所需的空 VM 数量。
      上一个列表中的脚本使用 dos.py 实用程序来管理 VM 及其快照(它在上一部中配置和安装)。您可以通过运行 dos.py -h 找到有关 dos.py 的所有信息。
  2. Gerrit 审查作业将开始构建插件。有关更多详细信息,请参阅 Gerrit 工作流程
    • a) 使用预配置的 Gerrit Trigger 在新的 Gerrit Patch 到达后启动您的作业
    • b) 运行代码语法检查器和单元测试,请按照 测试 中的说明进行操作
    • c) 运行 puppet linter(有关更多详细信息,请参阅 Puppet OpenStack 页面)
    • d) 构建插件(插件应通过 Fuel Plugin Builder 要求)
    • e) 触发插件测试
  3. 在 Gerrit patch 页面上投票并使用 Gerrit Trigger 在评论中添加审查结果。(可选)
  4. 插件测试(所有三个步骤都是来自 fuel-qa 仓库的 system_tests.sh 运行器的组成部分)
    • a) 安装插件
    • b) 配置环境
    • c) 部署带有非活动插件的环境
    • d) 运行 OSTF 测试。
  5. 运行插件特定的功能测试,以检查当前插件版本是否提供预期的功能。
  6. 将生成的聚合日志发布到日志存储。您可以通过归档日志来执行此操作。
自动化测试用例和测试框架

您应该遵循此建议来编写自动化测试并配置测试框架。请参阅以下链接以获取更多信息


首先,您应该准备环境并下载 Fuel ISO。

1. 克隆 GIT 仓库

git clone https://github.com/stackforge/fuel-qa

2. 通过运行激活虚拟环境

source ~/venv-nailgun-tests-2.9/bin/activate

3. 通过运行导出 Fuel ISO 路径

export ISO_PATH=path-to-iso

4. 进入此文件夹

cd fuel-qa/

通过运行此命令启动测试

./utils/jenkins/system_tests.sh -t test -w $(pwd) -j fuelweb_test -i $ISO_PATH -o --group=setup

或者,您可以安装一个空的设置,配置 1、3、5 或 9 个从机用于手动测试

 
fuel-qa$ ./utils/jenkins/system_tests.sh -t test -w $(pwd) -j fuelweb_test -i $ISO_PATH -o --group=prepare_slaves_5

system_tests 文件用作从 fuel-qa 仓库运行测试的运行器。

5. 有关测试工作原理和测试运行的更多选项,请阅读使用信息,通过运行

./utils/jenkins/system_tests.sh -h

在下文中,您可以找到有关主要文件和模块的信息

  • system_tests.sh - 测试开始执行的文件。此文件处理从命令行指定的参数并调用 run_tests.py
  • run_tests.py - 用于将您的测试文件导入到此文件中以运行您的测试。
  • settings.py - 包含用于环境定制的环境变量。使用此文件,您可以设置诸如 ISO 路径、节点数量等变量。

Models 文件夹中的文件提供了项目的核心逻辑

  • environment.py - 包含用于环境部署、虚拟机创建和网络配置的方法,以及在 Fuel Master 节点上安装 Fuel 等。

环境创建过程使用 devops 管理器 fuel-devops/devops/manager.py。Devops 管理器用于创建虚拟机,并使用较低级别的 libvirt 驱动程序。此外,环境模型包含用于 ssh 交互的方法。

  • nailgun_client.py - 包含 nailgun 处理程序、方法和 API 的功能。支持的 nailgun 客户端的方法和 API 可以在 此处 找到。Nailgun 客户端使用位于 helpers 文件夹中的 http 客户端。Nailgun 客户端用于 fuel web 客户端。

Fuel web 客户端包含诸如:集群创建、OSTF 测试启动、将节点添加到集群等方法。

Helpers 文件夹包含以下文件

  • checkers.py - 具有用于 ssh 客户端验证节点访问权限等的方法。
  • common.py - 具有用于 OpenStack API 访问、实例创建等的方法。
  • decorators.py - 具有不同的装饰器,最常用的装饰器是 ‘’log_snapshot_on_error’’;建议在所有测试中使用此装饰器,以防发生任何错误,将创建诊断和环境快照。
  • os_actions.py - 具有用于使用 OpenStack 的方法。


在编写您的第一个测试用例时,请注意以下事项

  • 对于编写您的第一个测试用例,您可以使用 ‘’test_fuel_plugin_example.py’’。
  • 在创建您自己的测试类时,您必须从位于 ‘’base_test_case.py’’ 的 TestBasic 类继承,其中执行 fuel web 客户端初始化。
  • 每个测试类和方法都必须用 ‘’@test’’ 装饰。
  • 测试组中的每个类都有组来一起运行所有测试用例,并且每个测试用例都有组来单独运行。
  • 测试用例具有 depends_on 方法或测试,这意味着此测试用例在 depends_on 方法或测试完成之前不会运行。

测试执行顺序

  1. 执行基本测试用例:这些测试用于设置环境并安装 Fuel Master 节点。
  2. 在这些测试通过后,将创建快照,这些快照将由测试用于创建集群。
  3. 恢复到先前创建的快照。
  4. 设置集群并部署它。
  5. 运行健康检查测试 (OSTF)。

对于测试执行调试,您可以使用 dos.py。您可以使用以下命令创建快照

dos.py snapshot <myenv> --snapshot-name=<snapshot_name>

您可以使用以下命令恢复快照

dos.py revert <myenv> --snapshot-name=<snapshot_name>

Fuel-qa 和 Fuel 插件

目前,Fuel 的系统测试保存在 fuel-qa 仓库中。请注意,对于实现 Fuel Plugin CI,可以将 fuel-qa 用作基线框架。这意味着,您可以使用该框架而无需将任何测试直接提交到 fuel-qa 仓库。

准备插件开发环境

通过三个简单的步骤准备您的插件开发环境

1. 安装标准的 Linux 开发工具。

  • 对于 Ubuntu 14.04 LTS,运行
   sudo apt-get install createrepo rpm dpkg-dev
  • 对于 Centos 6.5,运行
   yum install createrepo rpm rpm-build dpkg-devel

2. 安装 Fuel 插件生成器。为此,您应该首先获取 pip

   easy_install pip

3. 然后,安装 Fuel 插件生成器 (fpb)

   pip install fuel-plugin-builder

如果您需要安装最新版本的 Fuel 插件生成器,请按照以下说明操作

1. 克隆仓库

   git clone https://github.com/stackforge/fuel-plugins.git

2. 进入 'fuel_plugins' 文件夹

   cd fuel-plugins/

3. 安装 fpb

   sudo python setup.py install

使用 Fuel 插件生成器工具

插件结构

要构建您的插件,您应该首先生成其结构。它如下所示

Untitled drawing-3.png

生成结构和构建插件

要生成上述插件结构,您应该运行以下命令

fpb --create <fuel_plugin_name>

结果是,您只需要构建您的插件:fpb --build <fuel_plugin_name>

在构建插件后,您可以在插件的目录中看到它;例如,fuel_plugin_name/fuel_plugin_name-1.0.0.noarch.rpm"。

如何使用插件结构中的文件

deployment_tasks.yaml

引入了新的 "deployment_tasks.yaml" 文件来替换 "tasks.yaml"。新的文件可以使用新的参数 "required for" 和 "requires" 来指定任务依赖关系。

type: puppet
 groups: [primary-controller]
 required_for: [keystone]
 requires: [database]
 parameters:
    puppet_manifest: /etc/puppet/modules/osnailyfacter/modular/keystone/db.pp
    puppet_modules: /etc/puppet/modules
    timeout: 1800

“deployment_tasks.yaml” 的参数列表

role

该参数描述了将在其中执行任务的节点的角色。role 参数用于预/后部署任务或声明主部署的组。

该参数描述了具有指定角色的节点组,将在其中执行任务,并且应显式声明用于主部署。

- id: controller 
type: group
role: [controller]
requires: [primary-controller]
required_for: [deploy_end]
parameters:
strategy: 
type: parallel
amount: 6

“groups” 参数用于主部署。它与“role”参数冲突。任务必须具有“role”或“group”参数,但不能同时具有两者。

requires

该参数指定当前任务所需的任务列表。可以通过运行命令获取任务列表:fuel graph --env 1 --download

required_for

该参数指定当前任务是哪些任务所必需的。

timeout

您还可以指定秒的执行超时时间。指定后,如果超时过期,部署将失败。默认超时设置为 300 秒。

[fixme: 此信息仍然有用还是应该删除?]

Previously, when plugin developer set timeout for operation, this timeout worked differently for specific operations. For example:
  • shell 任务类型超时 = 超时 * 重试次数 (Mcollective 重试,默认 2 次)
  • puppet 任务类型超时 = 全局超时 (插件开发者设置的超时)。


现在它在两种情况下都正常工作:shell 和 puppet 任务类型具有全局超时。

[/fixme]

type: shell

该参数运行指定的 shell 命令

这是一个 "shell" 任务的示例

# This tasks will be applied on controller nodes,
# here you can also specify several roles, for example
# ['cinder', 'compute'] will be applied only on
# cinder and compute nodes
- id: task-shell-deploy
  role: ['controller']
  type: shell
  parameters:
    cmd: bash deploy.sh
    timeout: 42

- id: task-shell-deploy
  role: ['cinder','compute'']
  type: shell
  parameters:
    cmd: bash deploy.sh
    timeout: 42

# Task is applied for all roles
- id: task-shell-pluginlog
  role: '*'
  type: shell
  parameters:
    cmd: echo all > /tmp/plugin.all
    timeout: 42
type: puppet

Puppet 任务类型允许您将自己的 Puppet 清单应用于 OpenStack 节点。有关更多信息,请参阅 Fuel 中的 Puppet 部分。

要启用此任务类型,请首先在 deployment_scripts/puppet/manifests/ 目录中添加您的 site.pp 文件。然后将所有必需的模块放在 deployment_scripts/puppet/modules 目录中。

  • puppet_manifest - 指定相对于 deployment_scripts 的您的清单的目录路径。
  • puppet_modules - 指定相对于 deployment_scripts 的您的模块的目录路径。
# Deployment will be applied on controllers only
- role: ['controller']
  type: puppet
  parameters:
    puppet_manifest: puppet/manifests/site.pp
    puppet_modules: puppet/modules
    timeout: 360
type: reboot

从 Fuel 6.1 版本开始,对于具有 package_version: 2.0.0 的插件,reboot 任务类型允许您指定超时时间来重新启动节点。这对于应用节点上的大量更改非常有用。

- role: '*'
  type: reboot
  parameters:
    timeout: 300
type: group

一个 group 任务由要在指定节点上执行的任务列表组成。

- id: standalone-keystone 
  type: group 
  role: [standalone-keystone] 
  requires: [deploy_start, primary-standalone-keystone] 
  required_for: [deploy_end] 
  tasks: [fuel_pkgs, hiera, globals, tools, logging, netconfig, hosts, firewall, deploy_start, cluster, keystone-vip, cluster-haproxy, memcached, openstack-haproxy-stats, task-keystone] 
  parameters: 
     strategy: 
        type: parallel

当您设置任务组时,您还可以指定它们将如何执行:以“并行”或“逐个”方式。

strategy: type
* "parallel" - tasks will be executed in parallel
* "one-by-one" - tasks will be executed one-by-one

选择“并行”后,您可以使用“amount”参数指定可以并行运行的最大任务数。

- id: controller
 type: group
 role: [controller]
 requires: [primary-controller]
 required_for: [deploy_end]
 parameters:
   strategy:
     type: parallel
     amount: 6

environment_config.yaml

此文件描述将出现在 Fuel web UI 的“设置”选项卡上的其他属性。部署环境时,这些属性会传递给任务执行器,以便数据可在每个目标节点上的 /etc/astute.yaml 文件中提供,并可以从您的 bash 或 puppet 脚本中访问。

默认情况下,您的 environment_config.yaml 文件会在 Fuel web UI 上添加文本字段

attributes:
  fuel_plugin_name_text:
    value: 'Set default value'
    label: 'Text field'
    description: 'Description for text field'
    weight: 25
    type: "text"

有关插件的 Fuel web UI 元素,请参阅 Fuel 插件 UI 元素。

metadata.yaml

此文件包含您的插件的描述

# Plugin name
name: fuel_plugin_name
# Human-readable name for your plugin, it will be shown on UI
# as a name of plugin group
title: Title for fuel_plugin_name plugin
# Plugin version
version: 1.0.0
# Description
description: Enable to use plugin X
# Required fuel version
fuel_version: ['6.0']
# The plugin is compatible with releases in the list
releases:
  - os: ubuntu
    version: 2014.2-6.0
    mode: ['ha', 'multinode']
    deployment_scripts_path: deployment_scripts/
    repository_path: repositories/ubuntu
  - os: centos
    version: 2014.2-6.0
    mode: ['ha', 'multinode']
    deployment_scripts_path: deployment_scripts/
    repository_path: repositories/centos
# Version of plugin package
package_version: '1.0.0'
参数 用法 注释/示例
name 插件的内部名称。 名称可以包含小写字母、'-' 和 '_' 符号。
title 插件的人类可读名称,该名称将出现在 Fuel web UI 上。
description 您的插件的描述。 例如:为 Controller 角色节点启用 X 功能。
version 插件版本。 有关指南,请参阅 Semantic Versioning 2.0.0.
fuel_version 插件兼容的 Fuel 版本列表。 例如,2014.2-6.0。
package_version 插件版本;Fuel 使用此版本来选择应如何安装插件。 示例
is_hotpluggable 要启用在已部署的环境上安装插件,请将此参数设置为“true”。仅对没有核心功能的应用程序级别插件使用此参数。此外,插件必须定义 Fuel 可以应用于尚未配置的新节点上的角色。只要它们被配置到新节点上而不是先前配置或部署的节点上,该角色就可以与其他角色共存。 请参阅 模板,该模板默认将参数设置为“false”。
releases 插件兼容的 OpenStack 版本列表。 例如,2014.2-6.0。
os 受支持的 Linux 发行版的名称 例如,Ubuntu 或 CentOS
version OpenStack 版本的版本
mode 插件兼容的模式列表。 如果插件支持高可用性,则使用“ha”;如果不支持,则使用“multinode”。
deployment_scripts_path 插件目录中所有发布部署脚本的路径,相对于插件目录的顶部。
repository_path 插件目录中所有发布软件包的路径,相对于插件目录的顶部。 示例

插件部署顺序

从 Fuel 6.1 版本开始,您可以指定插件的部署顺序。如果多个插件应在一个环境中启用,这非常有用。例如,网络配置插件应在安装软件服务的插件之前运行。对于每个阶段名称,插件开发者添加一个后缀,该后缀定义了特定任务的执行顺序。让我们看一个例子

Fuel 插件 Atasks.yaml 文件

role: ['primary-controller', 'controller']
stage: post_deployment/100
type: shell
parameters:
    cmd: bash deploy.sh
    timeout: 42

Fuel 插件 Btasks.yaml 文件

role: ['primary-controller', 'controller']
stage: post_deployment/50
type: shell
parameters:
    cmd: bash deploy.sh
    timeout: 42


在 post_deployment 阶段执行期间,插件 B 的任务将在插件 A 的 post 任务之前运行,因为 post_deployment/50 低于 post_deployment/100。但是,在某些情况下,插件不知道彼此,因此解决问题的最佳方法是定义插件开发者可以使用范围的约定

0 - 999 硬件配置,例如驱动程序配置
1000 - 1999 保留供将来使用
2000 - 2999 磁盘分区和卷配置
3000 - 3999 保留供将来使用
4000 - 4999 网络配置
5000 - 5999 保留供将来使用
6000 - 6999 软件部署
7000 - 7999 保留供将来使用
8000 - 8999 监控服务部署

部署顺序在特定情况下的工作方式

  • 如果一个网络插件定义了阶段:post_deployment/100

而另一个插件的阶段为:post_deployment/2000,它们将在不知道彼此的情况下按正确的顺序安装。

  • 如果有两个插件实现监控,插件开发者

可以弄清楚哪个插件应该首先安装,并相应地调整后缀。

  • 如果两个任务具有相同的优先级,则应按字母顺序排序

按名称,并且列表中的第一个将首先部署。

  • 如果在单个插件中存在多个具有相同后缀优先级的任务,

则应按照它们在文件中指定的相同顺序部署它们。

  • 后缀可以是负数或正数,浮点数或整数。

其他阶段

可以定义其他插件特定的阶段

  • hw_configuration
  • disk_partitioning
  • network_configuration
  • software_installation

以及现有的阶段

  • pre_deployment
  • post_deployment


最后,一个新的阶段

  • monitoring

在这种情况下,插件开发者将能够使用单个实体而无需额外的后缀。

如何向用户显示插件限制

有时您可能需要在 Fuel UI 中为您的插件提供限制。这意味着所有不兼容的选项(例如,网络设置)都应以某种方式变灰。

什么是限制?

限制定义了何时应该提供设置和设置组。每个限制都定义为带有可选操作和消息的条件

restrictions:
  - condition: "settings:common.libvirt_type.value != 'kvm'"
    message: "KVM only is supported"
  - condition: "not ('experimental' in version:feature_groups)"
    action: hide
  • 条件是用 Expression DSL 编写的表达式。如果返回值为 true,则执行操作并显示消息(如果指定)。
  • action 定义了如果满足条件该做什么。支持的值为 "disable""hide""none""none" 值可用于仅显示消息。此字段是可选的(默认值为 "disable"
    • 禁用 - 插件复选框(放置在 Fuel Web UI 的设置选项卡中)变为非活动状态,并显示一个黄色三角形和一个弹出警告(当鼠标悬停时)。
    • 隐藏 - 当选择不正确的参数时,插件复选框将根本不会出现在 Fuel Web UI 的设置选项卡中。
    • 无 - 插件复选框保持活动状态,并显示一个黄色三角形和一个警告(当鼠标悬停时)。
  • 消息是在满足条件时显示的文本消息。此字段是可选的。
  • strict 是一个布尔标志,用于指定如何处理表达式中不存在的键。如果设置为 true(默认值),则在键不存在时会抛出异常。否则,这些键的值将为 null。将此标志设置为 false 对于依赖于插件提供的设置的条件非常有用。
restrictions:
  - condition: "settings:other_plugin == null or settings:other_plugin.metadata.enabled != true"
    strict: false
    message: "Other plugin must be installed and enabled"

限制也有简写形式

restrictions:
  - "settings:common.libvirt_type.value != 'kvm'": "KVM only is supported"
  - "settings:storage.volumes_ceph.value == true"
如何将限制添加到与插件相关的字段和复选框

请注意,您可以不仅将限制添加到复选框,还可以添加到与插件相关的字段。以下是 示例实现

attributes:
  # Show contrail only in supported network config
  metadata:
    restrictions:
      - condition: "not (cluster:net_provider == 'neutron' and networking_parameters:segmentation_type == 'vlan')"
        message: "Please use Neutron with VLAN segmentation, the only network type supported with Contrail plugin."
  contrail_asnum:
    value: '64512'
    label: 'AS Number'
    description: 'AS number for BGP communication'
    weight: 10
    type: "text"
    regex:
      source: '^(?:(6553[0-5])|(655[0-2]\d)|(65[0-4]\d{2})|(6[0-4]\d{3})|([1-5]\d{4})|([1-9]\d{1,3})|([1-9]))$'
      error: "Invalid AS number"
  contrail_private_cidr:
    value: '10.109.3.0/24'
    label: 'Private network CIDR'
    description: 'CIDR for private network used in Contrail inter-node communication'
    weight: 20
    type: "text"
    regex:
      source: '^(?:\d|1?\d\d|2[0-4]\d|25[0-5])(?:\.(?:\d|1?\d\d|2[0-4]\d|25[0-5])){3}(?:\/(?:[1-2]\d|[8-9]))$'
      error: "Invalid network CIDR"


这样的限制将在 Fuel Web UI 中显示如下: Plugin-restriction.png

示例实现

以下是 限制的示例实现

              - data: "disabled"
                label: "Mellanox drivers and plugins disabled"
                description: "If selected, Mellanox drivers, Neutron and Cinder plugin will not be installed."
                restrictions:
                  - "settings:storage.iser.value == true"
              - data: "drivers_only"
                label: "Install only Mellanox drivers"
                description: "If selected, Mellanox Ethernet drivers will be installed to support networking over Mellanox NIC. Mellanox Neutron plugin will not be installed."
                restrictions:
                  - "settings:common.libvirt_type.value != 'kvm'"
              - data: "ethernet"
                label: "Install Mellanox drivers and SR-IOV plugin"
                description: "If selected, both Mellanox Ethernet drivers and Mellanox network acceleration (Neutron) plugin will be installed."
                restrictions:
                  - "settings:common.libvirt_type.value != 'kvm' or not (cluster:net_provider == 'neutron' and networking_parameters:segmentation_type == 'vlan')"

如何将插件从 1.0.0 软件包版本迁移到 2.0.0

从 Fuel 6.1 开始,支持新的插件格式。请注意,新格式与 Fuel 6.0 不兼容。

对于新插件,Fuel Plugin Builder 构建 RPM 软件包,而不是 fuel 插件存档。

为了从旧格式迁移到新格式,请按照以下步骤操作

  • 获取最新的 fuel 插件构建器版本,2.0.0 或更高版本。
pip install fuel-plugin-builder
  • metadata.yaml 文件中 package_version 参数的值从 1.0.0 更改为 2.0.0
  • 运行以下命令
fpb --check plugin_path

并逐一修复错误,或按照以下说明操作。

更新

如果您的插件在 tasks.yaml 文件中使用“controller”角色,请确保您也指定了“primary-controller”。在新的插件中,“controller”和“primary-controller”应该明确定义。在以前的版本中,您可以指定“controller”,然后“primary-controller”会在后端自动添加。

全新功能

已向 metadata.yaml 文件添加了几个必填字段

  • groups 字段用于指定插件所属的组。可以使用以下选项之一
    • network
    • storage
    • storage::cinder
    • storage::glance
    • hypervisor
    • monitoring。

如果您的插件不属于这些选项中的任何一个,请将空列表设置为“groups”参数的值。

  • authors 字段提供作者列表。您应该在此处指定您或您公司的名称。
 Note: No commas should be used in authors field
       don't: 
       authors: ['Vyacheslav Struk, Mirantis', 'Oleksandr Martsyniuk, Mirantis']
       do: 
       authors: ['Vyacheslav Struk', 'Oleksandr Martsyniuk']
  • licenses 字段包含许可列表。
  • homepage 字段设置插件项目的链接。


请参阅 Contrail 插件 metadata.yaml 文件以获取示例。


引入了一种新的任务类型:reboot 任务对于执行需要重新启动的节点配置非常有用;例如,在配置 Linux 内核参数的情况下。有关 reboot 任务类型的更多信息,请参阅 Plugins wiki

插件版本控制系统

当需要交付新功能、次要更新或安全修复时,插件开发人员会创建插件的新版本;这可以是主要版本或次要版本

  • major - API、功能或主要 OpenStack 版本发生变化。
  • minor - 仅安全修复。


在 6.0 中,插件仅具有 .fp 格式。现在已弃用。在 6.1 及更高版本中,仅使用 RPM 插件。它们的版本控制方式如下

插件文件格式 fuel-plugin 值 metadata.yaml major minor
RPM fuel-plugin-1.0-1.0.0 1.0 1.0.0 1.0.0 1.0.1

例如:假设插件在 metadata.yaml 文件中具有 1.0.1 版本。那么插件文件应该具有不同的格式:plugin-1.0-1.0.1.rpm。

更新过程

更新 限制
fp NO
RPM 只能使用 fuel plugins --update <fuel-plugin-file> 命令更新到次要版本。要获取主要版本,用户必须从 Fuel Plugins Catalog 下载它并从头开始创建一个新环境。

版本控制方案

  • 对于 .fp 插件,完全不支持版本控制。这意味着用户必须从头开始下载和安装插件。
  • 对于 RPM 插件,如下所示

Rpm plugin versioning.png

重要提示

请考虑更改自定义软件包的版本控制方案,以便清楚地指示安装了哪个软件包 - 进入 Mirantis OpenStack 的软件包还是自定义软件包。

否则,需要检查 python 文件才能了解实际安装了哪个软件包。

内部工作原理

安装

安装过程包括以下步骤

  1. 用户使用安全复制将 fuel_plugin_name-1.0-1.0.0-1.noarch.rpm 文件复制到 Fuel Master 节点上。
  2. 然后,在将其复制到 Fuel Master 节点后,用户运行以下命令
    fuel plugins --install fuel_plugin_name-1.0-1.0.0-1.noarch.rpm
  3. Fuel 客户端将 fuel_plugin_name-1.0-1.0.0-1.noarch.rpm 软件包的内容安装到 /var/www/nailgun/plugins/fuel_plugin_name-1.0
  4. Fuel 客户端使用 REST API 服务(Nailgun)注册插件;它发送一个 POST 请求,其中包含 metadata.yaml 文件的内容到 /api/v1/plugins url。

配置

配置过程包括以下步骤

  1. 创建新环境时,Nailgun 会尝试查找与环境兼容的插件。
  2. Nailgun 将 environment_config.yaml 文件的内容与环境的基本属性合并,并为每个插件生成一个单独的组和 Fuel Web UI 上的复选框。
  3. 在用户启用它之前,插件处于禁用状态。在用户选择插件复选框后,Fuel Web UI 会将数据发送到 Nailgun。Nailgun 解析请求并在 Plugin 和 Cluster 模型之间创建关系。

仓库优先级

您可以配置插件的仓库优先级,而不是完全关闭它们,这可能会导致部署失败。您可以在 Nailgun 的 settings.yaml 中指定插件仓库的优先级。插件仓库的默认优先级如下

REPO_PRIORITIES: 
  plugins: 
    centos: 10 
    ubuntu: 1100

这些优先级应该高于 OS/Fuel 的优先级,因为用户可能希望覆盖 OS/Fuel 中的某些软件包。

通过 Fuel 插件的元数据预留虚拟 IP

一些插件需要额外的 VIP 才能启用正确的配置。以前,VIP 预留基于网络元数据。现在,它基于网络角色的描述。这使插件开发人员能够创建额外的 VIP,用于在开发人员的部署脚本中使用。

首先,用户应该在插件元数据中定义 VIP。然后,在创建环境之前安装插件。在未来的版本中,在创建环境之前安装插件的要求将被删除。

例如,Zabbix 可以配置为以一种方式接收 SNMP 流量,即在专用的 VIP 上接收 SNMP 流量。在这种情况下,插件开发人员可以在插件配置文件中定义额外的 VIP,并将其用作 puppet 资源。

VIP 预留只能通过插件元数据完成。这是通过添加一个名为 ‘network_roles.yaml’ 的新文件来完成的,该文件如下所示

- id: "name_of_network_role"
  default_mapping: "public"
  properties:
    subnet: true
    gateway: false
    vip:
      - name: "test_a"
        alias: "alias_name"
	namespace: "haproxy"
        node_roles: ["primary-controller", "controller"]
      - name: "test_b"

请注意,'alias'、'namespace' 和 'node_roles' 参数是可选的。

  • 'default_mapping' - 用于默认映射网络的网络名称。因此,VIP 将默认分配到该网络(可以在网络模板中更改该映射)。因此,如果应在不同的网络中分配 VIP,则应定义多个网络角色。
  • 'name' - 在环境中使用的唯一字符串,用于 Nailgun 数据库和编排器中的序列化。
 Note: Names for network interfaces are generated automatically using  first 13 characters of a VIP’s name. Therefore, if several VIPs are introduced by the same plugin, their names must differ in first 13 characters. Also, do not use the word ‘vip’ in a VIP’s name, as it will be added automatically where necessary.
  • 'alias' - 用于解决与 REST API 的兼容性问题,以便在 OpenStack 测试框架中使用旧记法运行测试。
  • 'namespace' - 指向用于 VIP 着陆的网络命名空间的字符串,如果未定义则为 null。
 Note: You must specify a namespace for a VIP,  otherwise it still will be put into network_metadata['vips'] in Hiera, where all available VIPs are stored, but not handled by Pacemaker. So, a plugin can use it in its own way.
  • 'node_roles' - 应设置 VIP 的节点角色的列表。如果未定义,其值为 ["primary-controller", "controller"]。
 Note: A node must have Pacemaker installed that automatically allocates resources for all VIPs. In Fuel 6.1, VIPs were processed manually.


已知问题:应该提到,插件只能请求新的网络角色。先前定义的 core 网络角色不能在插件中重新定义/扩展。有关更多信息,请参阅 LP1487011

使用新角色配置 Fuel 插件

从 Fuel 7.0 开始,在添加和启用自定义插件后,用户可以通过 Web UI 以及 Fuel CLI 定义插件中描述的新角色。在这种情况下,您可以在设置选项卡中从节点选项卡中的角色列表中选择一个插件角色,并将其附加到特定的节点。相反,当集群(环境)的插件被禁用时,它不应显示在角色列表中。

如果想要禁用插件,但集群中存在具有此插件角色的节点,请遵循现有机制:在节点选项卡中从所有节点中删除插件角色,然后在设置选项卡中禁用插件。

注意:在 Fuel 的早期版本中,当部署集群时,您无法禁用插件,因此无法从节点中删除插件角色。从 Fuel 8.0 开始,您可以删除自定义角色节点并重新部署环境。要正确删除自定义角色节点,请添加 "reexecute_on" 任务

  - id: my-task
    groups: [primary-controller, controller]
    reexecute_on: [deploy_changes]

此配置将在每次部署更改时在所有控制器上运行“my-task”任务。您可以使用这种方法处理缩减情况。

新的节点角色以及卷分区和任务信息可以在将集成到 Nailgun 中的 config yaml 文件中描述。Fuel 插件构建器应根据插件名称在 yaml 文件中自动创建一个新的节点角色。

描述节点角色在 ‘node_roles’ yaml 文件中的基本骨架

role_name:
  name: "Some plugin role"tasks
  description: "Some description"
  conflicts:
    - some_not_compatible_role
  limits:
    min: 1
  restrictions:
    - condition: "some logic condition"
      message: "Some message for restriction warning"

在 ‘volumes’ yaml 文件中描述卷分区

volumes:
  - id: "role_volume_name"
    type: "vg"
    min_size: {generator: "calc_min_os_size"}
    label: "Role specific volume"
    items:
      - mount: "/"
        type: "lv"
        name: "root"
        size: {generator: "calc_total_root_vg"}
        file_system: "ext4"
      - mount: "swap"
        type: "lv"
        name: "swap"
        size: {generator: "calc_swap_size"}
        file_system: "swap"
volumes_roles_mapping:
  role_name:
    - {allocate_size: "min", id: "os"}
    - {allocate_size: "all", id: "role_volume_name"}

以前,pre/post 部署任务仅保存在 tasks.yaml 中,这不允许指定任务依赖关系。现在,我们可以在 deployment_tasks.yaml 文件中描述具有任务依赖关系的部署任务。旧的 tasks.yaml 仍然受支持,但是建议使用新的 deployment_tasks.yaml。

在 ‘deployment_tasks.yaml’ 中描述一个新组

- id: role-name
  type: group
  role: [role-name]
  requires: [controller]
  required_for: [deploy_end]
  parameters:
    strategy:
      type: parallel

在插件角色的元数据中,开发人员可以描述与其他角色(例如 ‘openstack.yaml’ 中已存在的角色)的冲突。每个插件都应描述提供的角色列表,以便正确引用名称。

用户可以在一个插件中声明多个新的节点角色。这对于任务顺序和为插件开发人员构建自己的插件提供粒度方式很有用。

注意:也支持旧格式的插件。

注意:角色 '*' 受部署任务支持。此外,可以在角色的字段中指定任务名称列表。

部署

在创建并配置环境后,用户启动部署。同时,Nailgun 从数据库中获取启用的插件列表。对于列表中的每个插件,Nailgun 解析 tasks.yaml 文件

- role: ['controller']
  stage: post_deployment
  type: shell
  parameters:
    cmd: bash deploy.sh
    timeout: 42
- role: '*'
  stage: pre_deployment
  type: shell
  parameters:
    cmd: echo all > /tmp/plugin.all
    timeout: 42

例如,我们有一个已部署的两个节点环境。一个节点具有 UID 为 7 的 Controller 角色和 UID 为 8 的 Compute 角色。在这种情况下,任务执行器生成以下任务

{
    "pre_deployment": [
        {
            "uids": ["8", "7"],
            "parameters": {
                "path": "/etc/apt/sources.list.d/fuel_plugin_name-1.0.0.list",
                "data": "deb http://10.20.0.2:8080/plugins/
                fuel_plugin_name-1.0.0/repositories/ubuntu /"
            },
            "priority": 100,
            "fail_on_error": true,
            "type": "upload_file",
            "diagnostic_name": "fuel_plugin_name-1.0.0"
        },
        {
            "uids": ["8", "7"],
            "parameters": {
                "src": "rsync://10.20.0.2:/plugins/fuel_plugin_name-1.0.0/deployment_scripts/",
                "dst": "/etc/fuel/plugins/fuel_plugin_name-1.0.0/"
            },
            "priority": 200,
            "fail_on_error": true,
            "type": "sync",
            "diagnostic_name": "fuel_plugin_name-1.0.0"
        },
        {
            "uids": ["8", "7"],
            "parameters": {
                "cmd": "echo all > /tmp/plugin.all",
                "cwd": "/etc/fuel/plugins/fuel_plugin_name-1.0.0/",
                "timeout": 42
            },
            "priority": 300,
            "fail_on_error": true,
            "type": "shell",
            "diagnostic_name": "fuel_plugin_name-1.0.0"
        }
    ],
    "post_deployment": [
        {
            "uids": ["7"],
            "parameters": {
                "cmd": "bash deploy.sh",
                "cwd": "/etc/fuel/plugins/fuel_plugin_name-1.0.0/",
                "timeout": 42
            },
            "priority": 100,
            "fail_on_error": true,
            "type": "shell",
            "diagnostic_name": "fuel_plugin_name-1.0.0"
        }
    ],
    "deployment_info": "<Here is regular deployment info>"
}
任务 备注
pre_deployment 第一个子任务:由 Nailgun 自动生成。为节点添加一个新的仓库。仓库路径根据以下模板构建
http://{{master_ip}}:8080/plugins/{{plugin_name}}-{{plugin_version}}/{{repository_path}}
Where
  • master_ip 是 Fuel Master 节点的 IP 地址
  • plugin_name 是插件名称
  • plugin_version 是插件版本
  • repository_path 是 metadata.yaml 文件中的特定发布路径。

第二个子任务:由 Nailgun 自动生成。使用 rsync 将插件部署脚本复制到目标节点。文件路径与仓库路径非常相似。唯一的区别是部署脚本路径是从 metadata.yaml 文件中获取的 deployment_scripts_path。第三个子任务:由用户发起并从 tasks.yaml 文件获取,转换为任务执行器格式。

post_deployment 只有一个任务,该任务来自 tasks.yaml 文件;uids 字段包含一个列表,其中包含用户应在该节点上运行特定任务的节点。在本例中,tasks.yaml 文件具有“role: ['controller']”,并且该角色分配给控制器
deployment_info 包含部署所需的配置信息,与插件无关。

错误

特定插件的所有错误都在其项目中报告。
可以在 此处 找到现有 LP 项目的列表。
请注意,如果您的错误与 Fuel Plugin Framework 相关,您应该在 Fuel 项目中报告它。


重要性标准

开发错误

  • Critical = 无法部署任何内容且没有简单的解决方法;数据丢失;或安全漏洞
  • High = 某些硬件、配置或组件无法使用且没有解决方法;或者一切都已损坏,但有一个解决方法
  • Medium = 某些硬件、配置或组件工作不正确;或者完全无法使用,但有一个解决方法
  • Low = 次要功能已损坏,可以通过简单的解决方法修复;或者是一个外观缺陷
  • Wishlist = 不是真正的错误,而是一个建议的改进

文档错误

  • Critical = 遵循文档中的说明可能导致停机或数据丢失
  • High = 文档包含不正确的信息,或者说明无法产生广告效果
  • Medium = 文档中缺少重要信息(例如,新功能描述)
  • Low = 附加信息可以改善读者对功能的理解
  • Wishlist = 格式和语法问题

状态

所有错误,包括开发和文档,都具有以下状态

  • 新功能。当您发现一个错误时,应该将其提交到您的插件特定的项目中(如果与Fuel Plugin Framework相关,请使用 Fuel)。

“新”是默认状态,当错误报告提交时会自动分配给它。确保没有已经提交相同问题的错误报告(使用LaunchPad的高级搜索过滤器),然后输入您的报告详细信息。

  • 不完整。错误报告不完整,在可以进行分类之前需要更多信息。

如果您缺乏足够的信息来正确重现或评估错误的严重性,您应该向原始报告者请求更多信息。

  • 已确认。除了原始报告者之外的人认为该报告描述了一个真实的

错误,并且提供了足够的细节,以便开发人员可以开始修复。此人必须确保已设置了里程碑、重要性和负责人,并且设置正确。但该错误可能无法重现或确认其真实性。

  • 已分类(可选)。错误主管认为错误报告包含开发人员

开始修复工作所需的所有信息。修复错误的方案清晰可见,并且可以在评论中发布。有时,修复的实现会非常简单,您将直接跳到错误修复,但在其他情况下,您将发布完整的调试分析,并让其他人有机会修复该错误。

  • 正在处理。在此阶段,开发人员开始处理修复。在此期间,为了避免

重复工作,当开发人员开始处理该问题时,应立即设置此状态。请注意,当提交(发送第一个补丁集进行审查)并将在提交消息中添加“Closes-Bug”标签时,此状态将自动分配给该错误。如果开发人员未手动指定,则在发送第一个补丁集进行审查后,其姓名将出现在错误报告中。

  • 已修复并提交。一旦更改经过审查、接受和核心审查员批准(随

后合并到主分支),它将自动移动到“已修复并提交”状态。

  • 已发布。除了负责人之外的人已经验证了在应用修复后问题不再出现。

该状态留给 QA 在修复合并到主分支后标记错误为已验证。

如何报告错误

  1. 确保您已在 LaunchPad 上注册。如果还没有,请参阅官方 OpenStack 开发者指南
  2. 在 Launchpad 的 Fuel Plugins 项目中报告错误:输入 https://launchpad.net/fuel-plugins
  3. 点击 报告错误 链接
    Report-a-bug-lp.png
  4. 填写“摘要”字段以获取错误。它将成为标题。标题必须包含插件名称(例如,EMC Plugin)在方括号中。请具有描述性,但简短明了
    • 错误 - “<plugin-name> 无法安装”
    • 正确 - “<plugin name> 在选择“带有 VLAN 的 Neutron”网络时,在 HA 模式下安装失败”
  5. 输入“更多信息”。这是一个错误描述。让我们关注它所遇到的每一个问题
  6. 环境描述。提供足够的相关信息
    • 输出 http://fuel-master-node:8000/api/version/
    • 操作系统
    • 参考架构(HA / 非 HA)
    • 网络模型(Nova-network、Neutron+VLAN、Neutron+GRE 等)
    • 安装的相关项目(Savanna、Murano、Ceilometer)
  7. 重现步骤
    • 错误:在 HA 配置中运行部署
    • 正确:安装 Fuel Master 节点。将插件复制到 Fuel Master 节点并安装它。创建一个新的集群。
  8. 预期结果
    • 正确:插件已部署、启动并正在运行。
  9. 实际结果
    • 错误:插件安装失败。
    • 正确:插件安装失败,并显示错误消息“xxx”。请参阅附加的屏幕截图,其中显示“日志”选项卡上的错误。
  10. 解决方法
    • 错误:不要使用“带有 VLAN 的 Neutron”
    • 正确:应用补丁/将配置从 x 更改为 y。
  11. 影响
    • 错误:需要修复。
    • 正确:无法完成部署,因为客户要求我们为 Savanna 和“带有 VLAN 的 Neutron”实施用例。更改配置为“Neutron with GRE”在这里不是一个可接受的选项,因此必须尽快解决此问题。
  12. 在“此错误包含信息,即”字段下选择错误的可见性。默认情况下,将其保留为“公开”。
  13. 在“附加选项”部分下添加附件
  14. 日志
  15. 诊断快照
  16. 截图
  17. 添加 <plugin-name> 标签。
  18. 在输入所有内容后,选择“提交错误报告”按钮。


重要提示:请将私有错误保存在内部错误跟踪器中。不要在 LaunchPad 上报告这些错误。

常见的错误分类工作流程建议

在分类错误时,请考虑以下事项

  • 审查所有“新”错误。插件开发团队负责审查。要创建插件团队,请遵循 如何在 Launchpad 中创建插件开发团队
  • 将每个 “新” 错误定向到正在开发的发布里程碑,并设置相应的错误状态。
  • 考虑更改错误标题以使其更具体:替换诸如“部署超时”之类的通用语句,替换为根原因的描述(如果已识别)或该错误的独特症状。在错误标题和报告中使用标签,并在需要时手动创建新标签。
  • 假设 Fuel Plugins 项目中报告的所有错误都是公开的,请求缺失的信息,并将错误状态设置为“不完整”。添加一条评论,使用以下模板:我们没有收到正确解决问题所需的详细信息,因此我们将此错误设置为“不完整”状态。请提供所需的信息,我们将进一步调查此问题。 如果您认为它被错误地设置为“不完整”,请在错误中评论。
  • 如果提供足够的信息来重现错误,并且里程碑、重要性和负责人设置正确,请将状态设置为 “已确认”
  • 如果提供足够的信息来开始实施修复,请将状态设置为 “已分类”
  • 如果已确定错误的根本原因,请将其包含在错误描述中。
  • 审查所有 “不完整” 错误。
  • 如果 “不完整” 错误有新的更新,请按照上述针对 “新” 错误描述的相同步骤操作。
  • 如果 “不完整” 错误在 4 周内没有更新,请将其关闭为 “无效”。添加一条评论,使用以下模板:此错误不完整超过 4 周。我们无法进一步调查它,因此我们将状态设置为“无效”。如果您认为不正确,请随时提供更多信息并重新打开错误,我们将进一步查看。
  • 在新的发布范围确定期间,审查所有针对该发布里程碑的错误,确保由负责人(或如果错误未分配给人员,则由错误报告者)每天更新。
  • 错误的每个状态更改都应附带一条评论,解释进行更改的原因。


错误报告标签

为了更好地跟踪错误,请使用不同的标签

  • 每个插件都应该有一个自己的标签,格式为 <plugin name>。
  • 每个文档问题都应该标记为 docs

如何在 Launchpad 中创建插件开发团队

为了使插件的错误跟踪过程尽可能简单,插件开发人员应在 Launchpad 中创建自己的团队。以下是分步说明

  1. 输入 Launchpad 站点。
  2. 点击 注册团队 链接
    Registerteam.png
  3. 填写字段。您还应提供指向插件仓库、README.md 文件和 Fuel Plugins Catalog 的以下链接
    Fillin.png
  4. 选择成员资格策略
    Membership-pol.png
  5. 点击 创建团队 按钮完成。

有关添加成员和运行团队的信息,请参阅官方 Launchpad 指南。

教程

如何构建和从源代码安装插件

这些说明解释了如何从源代码仓库构建插件包。当您想要安装尚未在 Fuel 插件目录 上提供的插件版本时,这很有用。

1. 安装 fuel-plugin-builder 脚本。

2. 克隆插件的仓库。

git clone https://git.openstack.org/stackforge/fuel-plugin-neutron-fwaas

3. 进入插件目录,并切换到所需的 Git 分支或标签(可选)。

4. 构建插件包。

fpb --build ./fuel-plugin-neutron-fwaas

5. 生成的 RPM 包应可在当前目录中找到。按照插件的 README.md 文件中描述的其余安装过程进行操作。

如何调试 UI

UI 元素在 environment_config.yaml 文件中描述。要检查您构建的插件在 Fuel Web UI 上看起来如何,请安装并创建一个环境


1. 进入插件目录

cd fuel_plugin_name

2. 编辑 environment_config.yaml 文件

3. 构建插件

fpb --build <plugin_name>

4. 安装插件,使用“--force”参数替换已安装的插件(如果已安装)

fuel plugins --install fuel_plugin_name-1.0.0.fp --force

5. 创建新环境

fuel env --create --release 1 --name test

6. 检查 UI 是否正确显示 environment_config.yaml 文件中的元素

如何调试部署

为了展示它是如何工作的,让我们创建一个包含部署脚本中错误的简单插件。

1. 创建一个插件

fpb --create fuel_plugin_name

2. 在默认部署脚本 (fuel_plugin_name/deployment_scripts/deploy.sh) 中添加一个错误

#!/bin/bash
# It's a script which deploys your plugin
echo fuel_plugin_name > /tmp/fuel_plugin_name
# Non-zero exit code means, that a script executed with error
exit 1

3. 如果您不想运行插件构建,但想检查插件格式是否正确,可以使用带有以下命令的 --check 参数

fpb --check fuel_plugin_name

4. 构建并安装插件

fpb --build fuel_plugin_name/
fuel plugins --install fuel_plugin_name/fuel_plugin_name-1.0.0.fp

5. 使用 Fuel Web UI 或 CLI 创建一个环境

fuel env create --name test --rel 1 --mode multinode --network-mode nova

6. 在 Fuel Web UI 设置选项卡上启用插件,然后添加几个节点。第一个节点具有 Controller 角色,第二个节点具有 Cinder 和 Computes 角色。

fuel node set --node 1 --env 1 --role controller
fuel node set --node 2 --env 1 --role compute,cinder

7. 检查 Nailgun 是否生成用户可以在 Fuel Web UI 上设置的正确配置数据

fuel deployment --default --env 1
 cat deployment_1/controller_1.yaml
 ...
 fuel_plugin_name:
   fuel_plugin_name_text: Set default value
...

8. 现在可以看到目标节点的配置文件包含插件数据。

注意

The command mentioned above is useful when you do not know how your configuration data from Fuel web UI Settings tab will look like in /etc/astute.yaml file on target nodes.

9. 为两个节点执行不带部署的配置

fuel --env 1 node --provision --node 1,2

注意

To reduce the time required for testing, make a snapshot after nodes are provisioned. Note that if you use virtual machines, make snapshots of your target nodes.

10. 现在可以运行部署

fuel --env 1 node --deploy --node 1,2

11. 部署失败,并显示以下消息

Deployment has failed. Method deploy. Failed to deploy plugin fuel_plugin_name-1.0.0 

12. 您可以在 /var/log/docker-logs/astute/astute.log 任务执行器日志中看到一个错误

[394] Shell command failed. Check debug output for details
[394] 13edd324-6a11-4342-bc04-66c659e75e35: cmd: bash deploy.sh
cwd: /etc/fuel/plugins/fuel_plugin_name-1.0.0/
stdout:
stderr:
exit code: 1

13. 它由于您在第 2 步中对 deploy.sh 脚本所做的更改而失败。让我们假设我们不知道发生了什么,并尝试调试问题

# Go to the first node
ssh node-1

14. 所有插件部署脚本都复制到目标节点上的单独目录;在这种情况下,它是 /etc/fuel/plugins/fuel_plugin_name-1.0.0/

cd /etc/fuel/plugins/fuel_plugin_name-1.0.0/
# The directory contains our deploy.sh script, lets run it
bash deploy.sh
# And check exit code
echo $? # Returns 1

注意

If you use puppet for your plugin deployment, run the following command on the target node to check if your puppet manifests work correctly:

puppet apply --debug --modulepath=/etc/fuel/plugins/fuel_plugin_name-1.0.0/puppet/modules:/etc/puppet/modules /etc/fuel/plugins/fuel_plugin_name-1.0.0/puppet/manifests/site.pp

15. 现在我们可以看到部署由于非零退出代码错误而失败。要修复问题并检查提议的解决方案是否有效,请编辑 Fuel Master 节点上的 /var/www/nailgun/plugins/fuel_plugin_name-1.0.0/deployment_scripts/deploy.sh 脚本。请注意,无需重建和重新安装插件

#!/bin/bash

# It's a script which deploys your plugin
echo fuel_plugin_name > /tmp/fuel_plugin_name

# Now our deployment script returns 0 instead of 1
exit 0

16. 如果再次运行部署,它将成功

fuel --env 1 node --deploy --node 1,2

警告

During the testing of your deployment scripts, make sure that your scripts are idempotent: they should work correctly when applied several times. Run environment deployment at least twice and check that your plugin works properly. The reason for this workflow is the following: Fuel can run deployment of your plugin several times in case the first deployment try failed. Also, your deployment scripts can be executed during OpenStack patching.

17. 为了确保插件没有错误地工作,请还原第 6 步中创建的快照,然后再次运行部署

fuel --env 1 node --deploy --node 1,2

18. 以同样的方式,无需重新安装插件,您可以编辑 /var/www/nailgun/plugins/<fuel_plugin_name>-1.0.0/tasks.yaml 文件。请注意,在这种情况下,为了确保您的任务具有有效的格式,您至少应该运行以下命令

fpb --check /var/www/nailgun/plugins/fuel_plugin_name-1.0.0/

Fuel Web UI 中的插件元素

这是一个 environment_config.yaml 文件的示例,其中包含 Fuel Web UI 中的所有可能的元素

attributes:

  # Text field
  fuel_plugin_name_text:
    type: "text"
    weight: 10
    value: "Default text"
    label: "Text field label"
    description: "Field description"
    regex:
      source: '\S'
      error: "Error field cannot be empty"

 # Select
  fuel_plugin_name_select:
    type: "select"
    weight: 20
    value: "value2"
    label: "Select label"
    description: "Select description"
    values:
      - data: "value1"
        label: "Value 1 label"
      - data: "value2"
        label: "Value 2 label"
      - data: "value3"
        label: "Value 3 label"

  # Checkbox
  fuel_plugin_name_checkbox:
    type: "checkbox"
    weight: 30
    value: false
    label: "Checkbox label"
    description: "Checkbox description"

  # Radio button
  fuel_plugin_name_radio:
    type: "radio"
    weight: 40
    value: "disabled"
    label: "Radio buttons label"
    values:
      - data: "data1"
        label: "Label data1"
        description: "Description data1"
      - data: "data2"
        label: "Label data2"
        description: "Description data2"
      - data: "data3"
        label: "Label data3"
        description: "Description data3"

插件安装后,将在 Fuel Web UI 的设置选项卡上出现其他元素。以下是 Elasticsearch-Kibana 插件的 UI 元素

Ui-elements.png

Fuel 中的 Puppet

Fuel 不使用 master Puppet。任务执行器从 Fuel Master 节点复制清单,并在每个目标节点上运行 puppet apply 命令。建议在插件中使用 puppet 任务,而不是在 shell 任务中运行 puppet。任务执行器具有 具有特殊逻辑的代码,该逻辑处理错误,如果 puppet apply 命令返回零/非零退出代码。请注意,这并不意味着命令成功或失败。这意味着,如果在执行期间发生更改,它将返回“2”:任务执行器解析 /var/lib/puppet/state/last_run_summary.yaml 文件以确定 puppet 运行的状态。


如何使用插件将服务从 Controller 中分离

从 Fuel 7.0 开始,您可以创建和实施一个插件,该插件允许将任何角色或任务分解为部分并在自定义角色上部署。这包括启用高可用性功能。

Fuel 包含一个粒度部署框架,该框架依赖于基于任务的部署模式,定义如何部署每个节点角色。要修改粒度部署框架,您可以创建一个插件,该插件插入、覆盖或跳过任何给定的任务。此外,您可以添加任何自定义角色,以满足通常与 Controller 角色相关的任务。通常,所有 Controller 服务都直接部署在 Controller 节点上。

注意:在粒度部署中,跳过任务时会保留所有依赖关系。自定义角色必须在 Controller 角色之前或之后部署。例如,您不能在 Controller 上部署任务 A、B、C 和 D,暂停它,部署自定义 MyRole 角色,然后完成 Controller 角色上的任务 E 到 Z。因此,最好以自给自足的方式部署您的插件,该插件不依赖于 Controller 服务。

如果您想更改部署配置,请使用 Hiera 工具覆盖默认设置。

Hiera 概述

尽管 Puppet 在配置上是静态的,但它可以根据从外部数据源提供的数据定制部署。在这种情况下,Fuel 使用 Hiera 定义节点配置。

Hiera 是用于配置数据的键/值查找工具,但您可以配置它以定义数据源的优先级。

配置项存储在 3 种不同的数据结构中

  • 简单的键/值,
  • 数组,
  • 哈希。

示例

Key/value
role: “controller”
primary_controller: true
Array: amqp_hosts: [“192.168.0.3:5673”,”192.168.0.4:5673”,”192.168.0.5:5673”]
Hash: mysql: root_password: “OvEuZFyt” wsrep_password: “Secr3t”

Hiera 还提供了一层层配置数据的层次结构。默认情况下,它在其层次结构中具有多个优先级层级。默认的 /etc/hiera.yaml 文件如下所示

---
:backends:
 - yaml
:hierarchy: - override/node/%{::fqdn} - override/class/%{calling_class} - override/module/%{calling_module} - override/plugins - override/common - class/%{calling_class} - module/%{calling_module} - nodes - globals - astute
:yaml:  :datadir: /etc/hiera :merge_behavior: deeper :logger: noop

/etc/hiera/globals.yaml 中定义的所有值都优先于在 /etc/hiera/astute.yaml 中定义的值。对于更高层级中定义的所有值也是如此。如果一个插件定义了一个新的 YAML 文件并将其插入到层次结构中,它也可以覆盖给定的值。

对 Hiera 的查询有三种形式

  • 优先级,
  • 数组合并,
  • 哈希合并。

定义的值可以覆盖或与其他值合并。例如,您可以合并 astute.yaml 和自定义插件 YAML 中的 memcache_roles 数组,或者采用最高优先级。区别在于 Puppet 如何调用它

Merged lookup:
    hiera_array(‘memcache_roles’)
Priority lookup:
    hiera(‘memcache_roles’)

在大多数情况下,数组查找应使用优先级查找来完成。相反,Hiera 中的哈希查找应始终使用 hiera_hash 函数来完成。

示例

astute.yaml contains:
mysql:
 root_password: “OvEuZFyt”
 wsrep_password: “Secr3t”
plugins.yaml contains:
    mysql:
      enabled: false

如果您执行优先级查找而不是哈希查找,结果将大相径庭

Priority lookup:
    $ hiera mysql
    {“enabled”=>false}
Hash lookup:
    $ hiera -h mysql
    {“enabled”=>false,“root_password”=>“OvEuZFyt”,”wsrep_password”=>“Secr3t”}

Hiera 中的哈希合并允许插件开发者调整配置中的单个设置,而无需复制哈希中的所有其他值。

插件如何使用 Hiera

插件可以修改部署的任何 Hiera 配置数据,以告知现有任务如何部署。例如,如果您想在单独的 my-role 角色上运行 memcached,您可以覆盖 memcache_roles 数组,将其设置为 my-role 而不是 primary-controller, controller

将服务部署到单独的节点

可以通过覆盖 Hiera 中的元数据,如上所述,轻松关闭 Controller 角色上的 Rabbit 和 MySQL。可以通过禁用服务在其各自的服务哈希中的服务,这由一个值 enabled: false 表示来实现。但是,某些服务(如 Keystone)比较复杂,需要更多的配置。有关具体细节,请参阅下面的章节。

在插件中定义自定义角色

如果您想在与 Controller 不同的节点上部署单独的服务,首先需要定义一个自定义角色。

要在插件中定义自定义节点角色,请填写插件基本目录中的 node_roles.yaml 文件。替换现有任务的自定义角色必须包含一些特定的字段才能实现此目标。

除了默认属性之外,您还需在插件中包含以下属性

update_required
Corosync 主机、memcached 主机和 AMQP 主机在配置中显式列出。在添加/删除给定节点之前,将刷新指定角色中的所有现有节点。此列表应包括您正在部署的服务的所有使用者。
public_ip_required
仅内部服务(如 RabbitMQ)不应具有公共 IP。
has_primary
任何包含 corosync 的部署都需要此项。
conflicts
包含敏感数据的角色不应与 Compute 结合使用。在我们的示例中,我们还与 Controller 角色冲突,因为如果 controller 和 custom_role 角色与所有其他节点的映射不是 1:1,则可能会出现故障。

参见

配置 Hiera

数据库分离

数据库分离旨在尽可能灵活地适应各种部署配置,包括远程数据库创建、用户创建以及不同服务使用不同的数据库服务器。

以下是可配置的 MySQL 及其元数据的参数列表

  • MySQL 根密码(默认情况下自动生成)
  • db_host 或数据库 VIP
  • db_create(默认为 true)
  • db_user(默认为服务名称)
  • db_password(默认为自动生成的值)

此外,对于 Controller 角色上的 MySQL 哈希,您需要将 mysql 设置为 enabled: false

添加 HA

高可用性是任何生产部署的关键。每个服务都通过 corosync 或 haproxy 配置了 HA。

以下服务由 corosync 管理

  • 虚拟 IP 地址
  • haproxy
  • MySQL/Galera
  • RabbitMQ
  • Heat
  • Neutron 代理

这意味着您需要在自定义角色中包含以下任务之一或多个

  • cluster
  • cluster-haproxy
  • virtual_ips
  • openstack-haproxy-SERVICENAME
注意:由于 RabbitMQ 只需要 corosync 而不需要 haproxy 或虚拟 IP,因此它只需要集群任务来实现高可用性。另一方面,MySQL 和 Keystone 将需要这四项任务中的所有四项。

corosync 和 haproxy 的元数据要求已准备好通过 Hiera 接受自定义值。对于 corosync 本身,您需要一个键值,即 corosync_roles。这是必要的,因为 Corosync 的 UDP 配置需要所有节点显式允许彼此通信。该值应等于插件的角色名称,如下所示

corosync_roles:
  - primary-standalone-keystone
  - standalone-keystone
注意:这仅应在评估您的自定义角色时应用。请参阅 detach-keystone 插件 作为示例。

如果您想要分离的服务需要 HAProxy,请将以下数组包含在您的插件中

  • servicename_nodes
  • servicename_ipaddresses
  • servicename_nodes_names

请参阅 detach-keystone 插件 作为示例。

如果正在分离的服务需要 memcached,请在您的覆盖 Hiera YAML 中指定 memcache_roles。如果您的角色在 Controller 角色之前评估,这是必要的。但是,如果您的角色在 Controller 角色之后部署,则可以使用 Controller 角色中的 memcached,而无需更改此值。

RabbitMQ 分离

配置 Hiera 如下

  1. 在所有节点上设置 amqp_hosts 数组。由于原始主机列表是在粒状部署的 globals 任务中生成的,因此您需要覆盖此值而无需合并。由于没有要管理的虚拟 IP,因此它是唯一需要控制的值。
  2. rabbit_hash 设置为 enabled: false,用于 Controller 角色。
Keystone 分离

为了满足特定的用例,将 Keystone 服务从 Controller 角色中分离出来,请按照以下步骤操作

1. 在 Controller 节点上,查看已创建环境的任务列表
fuel graph --env 1 --download

我们关心的 keystone 任务是

keystone
创建 keystone 服务
keystone-db
准备 keystone 的 DB
openstack-haproxy-keystone
为 keystone 启用 haproxy
disable_keystone_service_token
admin_token 的清理任务
2. 将上述任务转移到自定义 keystone 角色(在我们的示例中是“standalone-keystone”角色)
  • 禁用原始 keystone 任务,创建一个名为 deployment_tasks.yaml 的 YAML 文件,并定义类型为 skipped 的新任务,以防止这些任务在 Controller 角色上运行
id: original_task_name
type: skipped
  • 创建一个新的任务,该任务重现原始任务,但替换原始任务的要求和角色

原始任务

- id: keystone-db
 type: puppet
 groups: [primary-controller]
 required_for: [keystone]
 requires: [database]
 parameters:
    puppet_manifest: /etc/puppet/modules/osnailyfacter/modular/keystone/db.pp
    puppet_modules: /etc/puppet/modules
    timeout: 1800

新任务

- id: keystone-db
 type: skipped
- id: task-keystone-db type: puppet role: [primary-standalone-keystone, standalone-keystone] required_for: [task-keystone] requires: [deploy_start, keystone-hiera-override, netconfig] parameters: puppet_manifest: /etc/puppet/modules/osnailyfacter/modular/keystone/db.pp puppet_modules: /etc/puppet/modules timeout: 1800
3. 确保所有新任务都相互依赖。

对于您创建的每个新任务,请确保其依赖关系与您标记为跳过的任务相符。在上面的示例中,task-keystone-dbtask-keystone 的依赖任务,task-keystone 是另一个执行相同功能的自定义任务。

参见

验证更改

  1. 创建一个环境来使用 1 个 Controller 节点和 1 个具有自定义角色的节点来测试您的任务图。
  2. 运行 fuel plugins --sync
  3. 运行 fuel graph --env 1 --download

如果成功,这些应该在没有错误的情况下运行。如果存在语法错误,则返回 500 错误。有关正确的 YAML 语法,请参阅 示例插件

程序和限制

RabbitMQ 程序

  1. 创建一个新的自定义角色。
  2. 启用 corosync(用于 HA)。
  3. 覆盖所有消耗 AMQP 的主机的 amqp_hosts 数组。
  4. 在 Controller 角色上禁用 rabbitmq。

Galera 程序

  1. 创建一个新的自定义角色。
  2. 启用 corosync(用于 HA)。
  3. 覆盖 mysql 哈希:为自定义角色启用它,为 Controller 角色禁用它。
  4. 为您的角色提供 database_viphaproxy

Keystone 程序

  1. 在 Controller 节点上禁用 Keystone 基本任务、haproxy 任务和 DB 任务。
  2. 创建一个新的自定义角色。
  3. 在自定义角色中添加 service_endpointpublic_service_endpoint VIP。
  4. 为 VIP 启用 corosync(但 keystone 本身是无状态的)。
  5. 启用 memcached。
  6. 启用对数据库插件的依赖。
  7. 对于 SSL 部署,在公共 VIP 上启用 Keystone 的 haproxy。

Keystone 分离的限制

  • Keystone 无法在没有 MySQL 和 memcached 的情况下运行。
  • Controller 角色提供这些角色,但您无法执行部分 Controller 部署、停止、部署 keystone 并继续。
  • Keystone 公共 SSL 限制为单个主机名。

Useful links

创建 Fuel 插件文档

Fuel 插件可以提供完全不同的功能,因此您不仅应该开发插件本身,还应该编写对最终用户清晰的文档。

文档包

为了让所有用户了解您的插件的功能以及如何进行测试,您需要在插件的 repo /doc 文件夹下 拥有以下文件

  • 测试计划 - 包含有关计划的测试活动的信息
  • 测试报告 - 包含在测试期间获得的信息
  • 插件指南 - 包含安装、配置和使用说明。


请注意,您的插件 repo 还应包含

  • 带有正确指定许可的 LICENSE 文件。
  • 添加到文件头部的特定 repo 文件的版权信息。有关详细信息,请参阅 相应部分
  • README 文件,其中包含有关如何构建您的插件的说明,请参阅 此处示例
  • 开发者规范 - 包含设计和实现细节,并解释了可以使用插件解决哪些问题。它被放入 /specs 文件夹中。


在编写时,请考虑 风格建议

遵循 Gerrit 工作流

Gerrit 工作流 为 Fuel 插件文档提供了以下优势

  • 使开发和文档编写周期保持一致。
  • 提供一次性发布特定的插件和相关的文档。
  • 提供以 RST 格式编写(如 specs 中已经使用的那样)。
  • 为开发者提供灵活的更新。


文档文件结构和 Sphinx 的使用

为了简化构建过程,您可以使用 Sphinx。

要在您的插件 repo 中启用它,请按照以下步骤操作

  1. 确保您的 repo 中有一个 /doc 文件夹(如图所示)。
  2. 考虑将您的插件指南拆分为较小的 RST 片段。可以在 此处 找到示例。
  3. 检查您是否已放置 index 文件。它将作为构建文档的来源。还需要对其进行编辑以包含 RST 片段(请查看示例)。
  4. 添加一个 Makefile,使用示例。通常将 Makefile 保持不变,以启用 PDF 和 html 构建(请查看 示例)。
  5. 编辑 conf.py 文件。此文件负责文档的外观,您可以根据自己的需要对其进行修改
  6. 提交您的更改。
  7. 尝试进入 /doc 文件夹并从中运行“make latexpdf”。

作为此练习的交付成果,您应该在 /build 文件夹中获得文档的 PDF 版本。

请参阅插件指南的推荐文件结构(作为示例):Doc-scheme-repo.png

风格建议

  1. 首次使用缩略词和缩写时,请拼写出来,并避免使用含义模糊的缩写。例如,“OS”可能表示“操作系统”或“OpenStack”。
  2. 不要在主要部分中添加许多指向外部资源的链接。建议将它们放在附录部分。
  3. 每个链接都应有一个简短的描述。确保定义安装/使用/测试插件所需的任何复杂概念和术语。
  4. 使用分步说明,结构化为介绍性句子,后跟要采取的编号步骤。


验收标准

插件相关文档(测试计划、测试报告、插件指南、规范)应满足以下验收标准

  • 文档以 RST 格式编写并放入插件 repo 中
  • 插件版本已正确指定;它必须与插件 metadata.yaml 文件中反映的版本相同。
  • 所有指向外部文档/资源的链接都存在并放在附录中
  • 所有复杂概念都以详细和清晰的方式进行了解释


请注意以下文档的一些具体建议

  1. 插件指南应包含安装和使用的两个主要部分。
    • 前者应侧重于 1) 如何/在哪里下载插件 2) 如何安装插件 3) 任何其他先决条件(例如后端配置)。
    • 后者应涵盖 1) 如何使用插件(例如,一组命令),并提供一个示例(强烈建议使用特定值使用命令) 2) 链接到外部文档。
    • 如果插件有自己的 UI 或假设在 Horizon 中采取某些操作,则插件指南必须包含带有清晰可见的 UI 元素的屏幕截图。
  2. 测试计划和测试报告必须有明确指定的先决条件才能使插件启动并运行。
  3. 插件规范必须涵盖设计和实现细节。请参阅 模板

检查清单

问题 如果完成,请打勾
插件版本与插件的 metadata.yaml 文件中指定的版本相同(请参阅 示例)。
所有关键术语/缩略词/缩写都放在相应的表中并清楚地解释,或者至少引用包含详细描述的其他资源。
插件名称在文档中不应发生变化(例如 VPNaaS 和 vpnaas)。坚持使用一种变体并在全文中使用。
如果特定组件的配置(如果有的话)未在文档中涵盖,则必须提供一个指向详细的分步说明的链接。
所有 UI 元素在屏幕截图中都应正确显示,甚至突出显示以指向特定操作/元素。
所有说明都应放入编号列表,以跟踪任务完成情况并沿文档导航。
所有关于 Fuel UI 向导或 Fuel Web UI 的说明均参考官方文档。

将您的插件添加到 DriverLog

一旦您的插件准备就绪,您可以按照 DriverLog wiki 页面 中的说明将其添加到 DriverLog。在添加之前,请确保

问题 示例 如果完成,请打勾
插件的文档已添加到 /doc 文件夹。 Midonet 插件
插件的规范已添加到 /specs 文件夹. Solidfire 插件
插件的 README 文件包含有关如何构建插件的说明。 Contrail 插件
插件的 LICENSE 文件包含相关的许可证。 Swiftstack 插件

许可证和版权

Fuel 插件采用 Apache 2.0 许可。
插件的仓库应包含以下内容

  • 许可证作为一个单独的文件 (LICENSE) - 请使用 官方许可证文本
  • 仓库中的所有文件(不包括配置文件和 README)都必须具有版权声明,请参阅 fuel-library 仓库


请注意,配置文件可以具有以下格式


Fuel 插件可以包含额外的组件。为了向用户提供此信息,请确保插件指南有一个单独的部分,其中包含以下表格

组件 许可
组件1 许可证1
组件2 许可证2

常见问题解答

我可以在哪里找到 Fuel 插件构建器源代码?

fuel-plugin-builder 位于 fuel-plugins 仓库中。

是否有插件示例?

现在 Fuel 的所有插件都在 Stackforge 项目下拥有自己的仓库。

如何重用 Fuel 中的 Puppet 模块? 根据设计,每个插件都应该拥有所有必要的组件,然后才能进行部署。这意味着每个插件都应该拥有 Fuel Puppet 模块的副本。如果您不想在您的仓库中保留 Fuel 库清单的副本,可以使用 pre_build_hook 在插件构建期间下载所需的模块。为此,将以下代码添加到您的 hook 中

#!/bin/bash
set -eux
ROOT="$(dirname `readlink -f $0`)"
MODULES="${ROOT}"/deployment_scripts/puppet/modules
mkdir -p "${MODULES}"
REPO_PATH='https://github.com/stackforge/fuel-library/tarball/f43d885914d74fbd062096763222f350f47480e1'
RPM_REPO="${ROOT}"/repositories/centos/
DEB_REPO="${ROOT}"/repositories/ubuntu/

wget -qO- "${REPO_PATH}" | \
    tar -C "${MODULES}" --strip-components=3 -zxvf - \
    stackforge-fuel-library-f43d885/deployment/puppet/{inifile,stdlib}

然后,该代码会从 fuel-library 仓库中复制 inifile 和 stdlib 模块。

警告

To reuse existing Puppet manifests you can also specify several Puppet modules in your task with colon separator: for example, puppet_modules: "puppet/modules:/etc/puppet/modules". Note that we do not recommend using this approach, because Fuel puppet modules can be changed during OpenStack update procedure; this can lead to compatibility failures.

如何下载插件所需的软件包? 在您的 pre_build_hook 脚本中使用 wget 将软件包下载到所需的目录中

#!/bin/bash
set -eux

ROOT="$(dirname `readlink -f $0`)"
RPM_REPO="${ROOT}"/repositories/centos/
DEB_REPO="${ROOT}"/repositories/ubuntu/

wget -P "${RPM_REPO}" http://mirror.fuel-infra.org/fuel-plugins/6.0/centos/glusterfs-3.5.2-1.mira2.x86_64.rpm
wget -P "${DEB_REPO}" http://mirror.fuel-infra.org/fuel-plugins/6.0/ubuntu/glusterfs-client_3.5.2-4_amd64.deb

它会在 Fuel Plugin Builder 开始构建仓库之前,将两个软件包下载到您的插件目录中。


为什么我在运行 pre_deployment 任务时没有 /etc/astute.yaml 文件? 如果您具有设置了“stage: pre_deployment”参数的任务,则在任务执行期间,您将无法在目标节点上找到 /etc/astute.yaml 文件。文件 /etc/astute.yaml 是一个在 Fuel 部署角色之前创建的符号链接。目标节点可以有多个角色,每个角色都包含自己的部署数据文件。以下是具有 ID 2 和两个角色(Controller 和 Cinder)的节点示例

root@node-2:~# ls -l /etc/ | grep yaml
-rw------- 1 root     root      8712 Nov 19 12:48 controller.yaml
-rw------- 1 root     root      8700 Nov 19 12:48 cinder.yaml

假设我们需要 Controller 角色的部署数据文件。我们可以在部署脚本中直接使用 '/etc/controller.yaml' 文件。

Fuel 插件 hook 的执行上下文是 root 还是 fuel 用户? 插件 hook 在 root 用户下执行。

Keystone IP 地址、用户名或密码是否可用于 post_deployment hook? Keystone admin_token、admin_password 位于 /etc/astute.yaml 中,可以在 post_deployment hook 中使用。要连接到 keystone,我们应该使用 management_vip:5000。management_vip 也位于 astute.yaml 中。还可以从 /root/openrc (OS_AUTH_URL) 获取 keystone url,但这是一种不太规范的方法。

多个 openstack controller 节点意味着多个 neutron­server 节点吗?Neutron server 安装在每个 controller 节点上。 所有 controller 节点的私有 IP(不是 VIP)是否可用且可从 post­deployment hook 访问?(因为我们希望 avi­controller、network etconly 运行一次,但我们必须在所有 neutron­server 节点上运行插件安装)?由于有多个 controller 节点,因此 fuel 基础设施会自动在每个节点上运行插件 post­deployment hook。

私有 IP 指的是 VM 的 IP,或者我们称之为管理 IP - OpenStack 中的每个人都以不同的名称称呼它。在 post_deployment 步骤中,所有网络、控制器等都已配置并运行。

在 pre-deployment 中,astute.yaml 是指向特定于角色的 yaml(controller、cinder 等)的符号链接,直到部署角色,但在 post-deployment 中 astute.yaml 是如何组织的 - 合并了所有角色的 yamls 吗? astute.yaml 文件在部署过程中不会合并。结果文件只是最后一个已部署角色的 astute.yaml。可以通过角色名称找到特定的 astute.yaml。

如何添加自定义角色? 当前的插件架构不提供定义角色的方法。从 Fuel 6.1 开始,您可以使用操作系统角色作为解决方法。

在 tasks.yaml 文件中使用 base-os 字符串来指定应使用哪个任务来部署角色。

- role: ['base-os']
  stage: post_deployment
  type: shell
  parameters:
    cmd: bash deploy.sh
    timeout: 42

在创建插件文档时,请要求用户在所需的节点上分配操作系统角色,并指定要为此节点指定的名称,例如 zabbix-01。在部署脚本中,您可以查询 user_node_name 变量,并决定是否应在节点上部署 Zabbix 相关软件包。

...
user_node_name: zabbix-01
...

沟通渠道

如果您还有其他问题,请随时使用 openstack-dev 邮件列表(使用 [fuel][plugin] 前缀)。有关邮件列表使用说明,请参阅 openstack-dev 邮件列表说明。