学习 OpenStack (4):基于 Pecan 开发 OpenStack 组件(Demo) _____2
前言
内容主要用作个人学习总结,如有描述错误,欢迎指明
进入正题之前建议先通过 pecan 框架实现一个 "hello world" ,Pecan: quick_start
这篇随笔将构建整合&验证API
目录结构
第 1 层
$ tree -L 1
.
|-- README.md
|-- etc # 存放本地配置文件,例如 *.conf、api_paste.ini 等
|-- libs # 环境构建过程较难安装的依赖包 *.whl
|-- log # 存放本地调试的日志
|-- pecan_demo # 项目
|-- setup.cfg # 安装: 声明式 配置文件
`-- setup.py # 安装: python 执行脚本
4 directories, 3 files
第 2 层
|-- pecan_demo
| |-- __init__.py
| |-- __init__.pyc
| |-- api # API 核心
| |-- cli # 预留的 Linux command
| |-- common # 公共模块
| |-- config.py # 预留配置文件,供 cfg 使用
| |-- config.pyc
| |-- db # 存储模块
| |-- messaging.py # 消息队列相关函数处理及封装
| |-- messaging.pyc
| |-- service.py # cfg 加载&初始化
| |-- service.pyc
| |-- version.py # 项目版本信息(pbr.version_info)
| `-- version.pyc
内部实现
接下来按加载顺序依次介绍
#1 定义启动文件
debug用
文件:pecan_demo/api/run.py
from wsgiref import simple_server
from pecan_demo.api import app
# import pdb
# pdb.set_trace()
application = app.build_wsgi_app(argv=[])
# print(type(application))
if __name__ == '__main__':
serve = simple_server.make_server('0.0.0.0', 8887, application)
serve.serve_forever()
#2 配置 cfg
文件:etc/oslo-config-generator/dev/pecan_demo.conf
[DEFAULT]
api_paste_config = 'F:\***\pecan_demo\etc\pecan_test_api\api_paste.ini'
log_dir = F:\***\pecan_demo\log
auth_strategy = keystone
[database]
connection = mysql+pymysql://root:123456@localhost/pecan_demo
文件:pecan_demo/api/app.py
auth_opts = [
cfg.StrOpt('api_paste_config',
default="api_paste.ini",
help="Configuration file for WSGI definition of API."),
cfg.StrOpt('auth_strategy',
choices=['noauth', 'keystone'],
default='keystone',
help=("The strategy to use for auth. Supports noauth and "
"keystone")),
]
# CONF.register_opts(auth_opts, group='DEFAULT')
CONF.register_opts(auth_opts)
所有 *.conf 里的配置项,都要在项目初始化时,在 cfg 里注册;oslo.config 相关的介绍网上太多了,不赘述 贴两个参考 、
#3 加载 cfg
文件:pecan_demo/service.py
def prepare_service(argv=None, config_files=None):
if argv is None:
argv = sys.argv # 命令行参数预留
oslo_i18n.enable_lazy() # 国际化模块
log.register_options(cfg.CONF) # 日志配置加载
log.set_defaults()
defaults.set_cors_middleware_defaults()
# 配置解析(建议用 rpdb 断点调试这里,可以加深 oslo.config 模块的理解)
cfg.CONF(argv[1:], project='pecan_demo', validate_default_values=True,
version=version.version_info.version_string(),
default_config_files=config_files)
log.setup(cfg.CONF, 'pecan_demo')
messaging.setup()
return cfg.CONF
#4 Pecan 初始化
文件:pecan_demo/api/app.py
from pecan_demo.api import config as api_config
from pecan_demo.api import hooks
def get_pecan_config():
# Set up the pecan configuration
filename = api_config.__file__.replace('.pyc', '.py') # api/config.py
return pecan.configuration.conf_from_file(filename)
def setup_app(pecan_config=None, extra_hooks=None):
app_conf = get_pecan_config()
app_hooks = [
hooks.ContextHook(), # Pecan钩子,程序有预加载的数据或驱动,可以放在这里
]
app = pecan.make_app(
app_conf.app.root, # 视图的根节点
static_root=app_conf.app.static_root,
template_path=app_conf.app.template_path,
debug=CONF.api.pecan_debug,
force_canonical=getattr(app_conf.app, 'force_canonical', True),
hooks=app_hooks,
guess_content_type_from_ext=False
)
return app # wsgi application
文件:pecan_demo/api/config.py
# Pecan Application Configurations
app = {
'root': 'pecan_demo.api.root.RootController', # 视图根节点
'modules': ['pecan_demo.api'],
'static_root': '%(confdir)s/public',
'template_path': '%(confdir)s/templates',
'debug': False,
'enable_acl': True,
'acl_public_routes': ['/', '/v1'],
}
#5 视图&路由
Pecan 路由规则
视图结构
|-- api
| |-- __init__.py
| |-- __init__.pyc
| |-- app.py
| |-- app.pyc
| |-- config.py
| |-- config.pyc
| |-- hooks.py
| |-- hooks.pyc
| |-- middleware.py
| |-- root.py # RootController
| |-- root.pyc
| |-- run.py
| `-- v1 # API 版本控制,便于切换 .../v1/... or .../v2/...
| |-- __init__.py
| |-- __init__.pyc
| |-- controllers # 业务代码
| | |-- __init__.py # 集成各个模块的控制器
| | |-- __init__.pyc
| | |-- demo.py # 按功能或业务划分控制器,例如:demo
| | `-- demo.pyc
| `-- datamodels # 对应存放各模块控制器,出入参的 schema
| `-- __init__.py
文件:pecan_demo/api/root.py
from pecan_demo.api.v1 import controllers as v1_api
class RootController(rest.RestController):
"""Root REST Controller exposing versions of the API.
"""
v1 = v1_api.V1Controller() # root 控制器
@wsme_pecan.wsexpose([APIVersion])
def index(self):
...
文件:pecan_demo/api/v1/controllers/init.py
from pecan import rest
from pecan_demo.api.v1.controllers import demo as demo_api
class V1Controller(rest.RestController):
"""API version 1 controller.
"""
demo = demo_api.DemoController()
文件:pecan_demo/api/v1/controllers/demo.py
import pecan
from pecan import rest
class DemoController(rest.RestController):
@pecan.expose()
def index(self):
return 'DemoController'
#6 IDE 调试
...
铺垫基本完成了,剩下的要将代码放到 Linux 系统中调试,对接 OpenStack 组件的 API