OpenStack模块代码结构

1.简介

在开始介绍各个OpenStack服务的Puppet模块前,先观察一下所有OpenStack module的目录结构,你会发现所有的模块的部分代码目录结构和命名方式几乎是一致的,这是经过了长期迭代和开发中形成的规范和统一,代码结构统一带来的好处有两点:

  1. 易于维护人员理解和管理

  2. 减少冗余代码,提高代码复用

那么我们就来看看一个OpenStack服务的Module中包含了哪些目录:

  • examples/ 放置示例代码

  • ext/ 放置external代码,和主要代码无关,但是一些有用的脚本

  • lib/ 放置library代码,例如自定义facter,resource type

  • manifests/ 放置puppet代码

  • releasenotes/ 放置releasenote

  • spec/ 放置class,unit,acceptance测试

  • tests/ 已弃用,使用examples替代

以上目录中最重要的是manifests目录,用于放置Puppet代码,在该目录下包含了以下通用代码文件:

名称

说明

init.pp

主类,也称为入口类,通常仅用于管理公共参数(如MQ参数)

params.pp

用于特定操作系统的参数值设置

client.pp

管理客户端的配置

config.pp

用于管理自定义的参数配置

policy.pp

policy设置

db/

支持多种数据库后端的配置

keystone/

keystone endpoint,service,user,role的设置

2.数据库管理

2.1 class <service>::db

class <service>::db用于管理各OpenStack服务中的数据库相关配置,<service>是OpenStack服务的名称,以Aodh为例:

class aodh::db管理了与数据库相关的配置项,其中通过调用oslo::db来实现,关于puppet-oslo模块,本书会在下一章节详细说明。

2.2 class <service>::db::mysql

class <service>::db::mysql用于创建相关服务的MySQL数据库,用户和授权等。以Aodh为例:

class aodh::db::mysql管理了MySQL aodh数据库的创建,aodh用户创建和密码设定,数据库编码,访问授权等。其调用了openstacklib::db::mysql来实现上述功能,关于puppet-openstacklib模块,本书会在下一章节详细说明。

2.3 class <service>::db::postgresql

class <service>::db::mysql用于创建相关服务的PostgreSQL数据库,用户和授权等。以Aodh为例:

class aodh::db::postgresql完成了aodh数据库的创建,aodh用户创建和密码设定,数据库编码,访问授权等。其调用了openstacklib::db::postgresql来实现上述功能。

2.4 class <service>::db::sync

class aodh::db::sync用于执行数据库表的初始化和更新操作。以Aodh为例:

aodh::db::sync的实现是通过声明exec资源来调用aodh-dbsync命令行完成数据库初始化的操作。

3. Keystone初始化管理

在OpenStack部署工作中,与Keystone相关的初始化操作是集群正常运行必不可少的步骤:

  • 创建Domain

  • 创建Project

  • 创建User,设置Password

  • 创建并指定Role

  • 创建Service

  • 创建Endpoint

也包括在后期的运维中,指定user的password更新或者endpoint的更改等常见操作都可以在Puppet中完成。而这背后的工作是通过<service>::keystone::auth来完成的。

3.1 class <service>::keystone::auth

<service>::keystone::auth用于创建OpenStack服务的user,service和endpoint,以Aodh为例:

实际上aodh::keystone::auth在声明define keystone::resource::service_identity的基础上,根据Aodh服务而重写了相关的参数。

下面来看一段代码,关于keystone::resource::service_identity如何实现service的管理:

通过函数ensure_resource调用了keystone_service自定义资源类型,并传入两个参数:

  • "${service_name_real}::${service_type}"

  • {'ensure' => $ensure, 'description' => $service_description,}

有细心的读者读到这里可能会好奇,把服务名称和服务类型作为一个参数传入keystone_service,它是怎么区分的?

先来看keystone_service.rb的代码片段(代码路径puppet-keystone/lib/puppet/type/keystone_service.rb):

title_patterns方法通过调用PuppetX::Keystone::CompositeNamevar.basic_split_title_patterns方法来得到:name:type变量。

接着跳转到basic_split_title_patterns的定义(代码路径lib/puppet_x/keystone/composite_namevar.rb):

可以看到basic_split_title_patterns方法默认使用'::'作为分隔符,通过not_two_colon_regex函数进行正则匹配并切割字符串。 至此,我们从上到下地剖析了如何实现Keystone相关资源的初始化,以加深读者对于代码的理解。在实际使用中,对于终端用户来说,并不需要关心底层的Ruby代码。

3.2 class <service>::keystone::authtoken

<service>::keystone::authtoken用于管理OpenStack各服务配置文件中的keystone_authtoken配置节。以Aodh服务为例:

aodh::keystone::authtoken定义中声明了define keystone::resource::authtoken,并重写了部分参数的默认值。 keystone::resource::authtoken中定义了hash类型变量$keystonemiddleware_options,涵盖了keystone_authtoken配置节下的所有参数, 最终通过调用create_resources函数,传入服务名称参数$name,从而完成指定服务配置文件中keystone_authtoken的配置。

4.维护不同Linux发行版之间的数据

PuppetOpenstack支持在Redhat, CentOS, Ubuntu等多个Linux发行版上部署OpenStack服务,然而在不同的Linux发行版中,同一个OpenStack服务的软件包的名称会有所不同。

例如,Nova API软件包的名称在Redhat下是'openstack-nova-api',在Debian下是'nova-api'。

而这些数据则通过各个模块的class <service>::params维护。

以keystone::params为例,可以看到不同的Linux发行版之间$package_name, $service_name等参数值也有所不同:

5. 管理自定义配置项的<service>::config

模板是用于管理配置文件的常见方式,对于成熟的项目而言,模板是一种理想的管理配置文件方式。但对于快速迭代的项目如OpenStack,维护人员会非常痛苦,每增删一个配置项需要同时更新模板和manifets文件。

试想一个module的更新若都在参数的增添上,那对社区开发者来说是极大的成本。有没有一种办法可以不修改module,直接在hiera里定义来添加新配置项呢?

<service>::config类是由笔者在14年初提出的特性,目的是灵活地管理自定义配置项。

自定义配置项是指未被模块管理的参数。怎么理解?

keystone::config为例,其核心是create_resources函数以及keystone_config/keystone_paste_init自定义资源:

若Keystone在某版本新增了参数new_param,在puppet-keystone模块里没有该参数,此时,只要使用keystone::config就可以轻松完成参数的管理。

在hiera文件中添加以下代码:

6.管理客户端 <service>::client

<service>::client用于管理各OpenStack服务的Client端,完成客户端的安装。

以Nova为例,nova::client完成了python-novaclient软件包的安装:

7. 管理策略<service>::policy

<service>::policy用于管理Openstack各服务的策略文件policy.json。

以Cinder为例,下面是cinder::policy代码:

其中使用create_resources调用了openstacklib::policy::base,以及声明了oslo::policy定义。

Last updated

Was this helpful?