OpenStack 源码中的OSLO

Oslo

在RYU的目录下可以找到cfg.py文件,这个文件中import了oslo的相关模块,以便调用时减少引用数目。从文件中可以发现oslo.config.cfg文件是关键文件,其在系统中的文件位置在:/usr/local/lib/python2.7/dist-packages/oslo/config/cfg.py。想查看源码的读者可以自行查看。在该cfg.py文件中 定义了ConfigOpts类,包含了_opts, _groups等成员变量。该类完成了命令行和配置参数的解析。

如果要快速学习某一个知识,最好的办法就是把它用起来。所以首先我会介绍一个入门的教程。如果你没有看懂,可以去看原始的教程

首先安装python-virtualenv,此python库可以用于创建一个虚拟的,与外界隔离的运行环境,听起来和docker好像有点像。

1
2
3
4
5
6
7
sudo apt-get install python-virtualenv
virtualenv example-app
cd example-app
source bin/activate
pip install oslo.config
touch app.py
touch app.conf

然后修改app.conf。添加了两个group:simple和morestuff。simple组中有一个BoolOpt:enable。morestuff组有StrOpt, ListOpt, DictOpt, IntOpt,和FloatOpt。

1
2
3
4
5
6
7
8
9
10
11
12
13
[simple]
enable = True
[morestuff]
# StrOpt
message = Hello World
# ListOpt
usernames = ['Licheng', 'Muzixing', 'Distance']
# DictOpt
jobtitles = {'Licheng': 'Manager', 'Muzixing': 'CEO', 'Distance': 'Security Guard'}
# IntOpt
payday = 20
# FloatOpt
pi = 3.14

修改app.py文件。首先定义两个group,再对两个group的option进行定义。最后使用register_group和register_opts函数来完成group和option的注册。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from __future__ import print_function
from oslo.config import cfg
opt_simple_group = cfg.OptGroup(name='simple',
title='A Simple Example')
opt_morestuff_group = cfg.OptGroup(name='morestuff',
title='A More Complex Example')
simple_opts = [
cfg.BoolOpt('enable', default=False,
help=('True enables, False disables'))
]
morestuff_opts = [
cfg.StrOpt('message', default='No data',
help=('A message')),
cfg.ListOpt('usernames', default=None,
help=('A list of usernames')),
cfg.DictOpt('jobtitles', default=None,
help=('A dictionary of usernames and job titles')),
cfg.IntOpt('payday', default=30,
help=('Default payday monthly date')),
cfg.FloatOpt('pi', default=0.0,
help=('The value of Pi'))
]
CONF = cfg.CONF
CONF.register_group(opt_simple_group)
CONF.register_opts(simple_opts, opt_simple_group)
CONF.register_group(opt_morestuff_group)
CONF.register_opts(morestuff_opts, opt_morestuff\_group)
if __name__ == "__main__":
CONF(default_config_files=['app.conf'])
print('(simple) enable: {}'.format(CONF.simple.enable))
print('(morestuff) message :{}'.format(CONF.morestuff.message))
print('(morestuff) usernames: {}'.format(CONF.morestuff.usernames))
print('(morestuff) jobtitles: {}'.format(CONF.morestuff.jobtitles))
print('(morestuff) payday: {}'.format(CONF.morestuff.payday))
print('(morestuff) pi: {}'.format(CONF.morestuff.pi))

完成之后,运行app.py文件。可以查看到相关输出。

回到RYU中,之前一篇博客介绍了RYU的main函数。在ryu/ryu/cmd/manager.py文件中我们可以看到如下的代码:

1
2
3
4
5
6
7
CONF.register_cli_opts([
cfg.ListOpt('app-lists', default=[],
help='application module name to run'),
cfg.MultiStrOpt('app', positional=True, default=[],
help='application module name to run'),
cfg.StrOpt('pid-file', default=None, help='pid file name'),
])
1
2

以上的注册了三个Option,其中的app-lists和app参数是运行ryu-manager时的参数,即APP的名称。在以下的main函数中,我们可以看到首先获取了输入的参数,若参数为空,则默认开启ofp\_handler应用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def main(args=None, prog=None):
try:
CONF(args=args, prog=prog,
project='ryu', version='ryu-manager %s' % version,
default_config_files=['/usr/local/etc/ryu/ryu.conf'])
except cfg.ConfigFilesNotFoundError:
CONF(args=args, prog=prog,
project='ryu', version='ryu-manager %s' % version)

log.init_log()

if CONF.pid_file:
import os
with open(CONF.pid_file, 'w') as pid\_file:
pid_file.write(str(os.getpid()))

app_lists = CONF.app_lists + CONF.app
# keep old behaivor, run ofp if no application is specified.
if not app_lists:
app_lists = ['ryu.controller.ofp_handler']

oslo模块使用能够使得整个工程的不同模块可以使用同一个配置文件,从而减少了命令冲突的可能,此外,oslo提供的模板,可以让命令解析更方便。在oslo.config之外,还有oslo.db,oslo.messaging等。

  针对OpenStack 多个组件,OpenStack社区开发了不少公共组件OSOL:https://github.com/openstack/?query=oslo