OpenStack公共组件oslo之十四——pbr

        pbr库是一个使用统一方式管理setuptools包的库。pbr库通过一个setup钩子函数读取并过滤setup.cfg中的数据,以填充默认值并提供更多合理的操作;然后将结果作为参数返回给setup.py。因此,处理Python包安装的大量繁重工作仍然交给setuptools包处理,pbr只为setuptools读取和过滤所需要的参数即可。需要注意的是,pbr并不支持setuptools的easy_install功能,尽管pbr依赖setup_requires,但对于install_requires还是需要手动或使用pip进行安装。本文将详细分析pbr的实现原理和使用方法。

1 pbr的使用场景

        目前,pbr可以实现很多功能,主要包括以下几个方面:
  1. version:基于git的修订版本和标签来管理版本号。
  2. AUTHORS:从git log命令生成AUTHORS文件。
  3. ChangeLog:从git log命令生成ChangeLog文件。
  4. Manifest:从git文件和一些标准文件中生成一个合理的Manifest清单。
  5. Sphinx Autodoc:为整个模块生成autodoc存根文件。
  6. Requirements:将依赖库保存在一个pip的requirements文件中。
  7. long_description:使用README文件作为一个库的描述信息。
  8. Smart find_packages:在根目录下智能找到相应的软件包。

2 pbr的实现原理

2.1 hook的实现

        本文开始介绍pbr会通过一个setup钩子函数读取并过滤setup.cfg文件中的数据,因此本文首先就来介绍一下pbr的hook函数的实现。pbr的hook函数的实现都放在pbr.hooks中,首先pbr创建了一个配置基类BaseConfig,该类中首先定义了一个钩子方法hook()的空实现,然后定义了一个save()方法保存配置信息,最后定义了一个模板方法run()。在这个模板方法中,首先调用hook()方法过滤读取到的配置信息,然后调用save()方法保存过滤后的配置信息。因此,在实现具体的配置实体时,需要重写hook()和save()方法。而pbr的hook函数的实现主要包括以下几个:
  • MetadataConfig类:该类获取setup.cfg文件中section为metadata的配置信息,即获取待安装的包的元数据,包括其名称、版本、描述等信息。
  • CommandsConfig类:该类获取setup.cfg文件中section为global的配置信息,即获取一些安装命令对应的程序。
  • FilesConfig类:该类获取setup.cfg文件中section为files的配置信息,即获取对应的包与配置文件路径等。
  • BackwardsCompatConfig类:该类获取setup.cfg文件中section为backwards_compat的配置信息,即获取依赖相关的配置信息。
        为了使用这些钩子函数获取对应的配置信息,pbr在pbr.hooks模块下定义了setup_hooks()方法调用了上述这些钩子函数。
from pbr.hooks import backwards
from pbr.hooks import commands
from pbr.hooks import files
from pbr.hooks import metadata


def setup_hook(config):
    """Filter config parsed from a setup.cfg to inject our defaults."""
    metadata_config = metadata.MetadataConfig(config)
    metadata_config.run()
    backwards.BackwardsCompatConfig(config).run()
    commands.CommandsConfig(config).run()
    files.FilesConfig(config, metadata_config.get_name()).run()

2.2 pbr的实现

        2.1节中介绍了pbr中定义的钩子函数,接下来将会结合钩子函数讨论pbr的实现。使用pbr安装包的实现主要放在pbr.core模块中,在该模块中主要定义了一个pbr(dist, attr, value)方法来获取安装时所需要的参数。在使用中,除了setup_requires外,pbr方法应该是setup()方法的唯一参数。该方法首先获取setup.cfg文件的路径,然后会调用pbr.util模块中的cfg_to_args(path='setup.cfg', script_args=())方法获取setuptools所需的配置参数。
        cfg_to_args(path='setup.cfg', script_args=())方法则是通过配置的setup_hooks()方法读取setup.cfg文件中的配置信息,除了使用hook函数外,该方法还对一些可选配置项进行了读取,如entry_endpoints等,然后将结果作为参数返回给setup()方法进行软件包安装操作。
        当然,除了实现pbr功能外,针对第1节中提到的使用场景,pbr库都有相应的实现,在此不再作过多分析,感兴趣的朋友可以参考 pbr官方文档

3 pbr的使用

        pbr的实现非常简单,这里以nova组件的setup为例简单介绍一下pbr的使用。通过上述分析,我们知道使用pbr,首先需要一个setup.cfg配置文件,nova组件的setup.cfg配置文件内容如下所示:
[metadata]
name = nova
summary = Cloud computing fabric controller
description-file =
    README.rst
author = OpenStack
author-email = openstack-dev@lists.openstack.org
home-page = https://docs.openstack.org/nova/latest/
classifier =
    Environment :: OpenStack
    Intended Audience :: Information Technology
    Intended Audience :: System Administrators
    License :: OSI Approved :: Apache Software License
    Operating System :: POSIX :: Linux
    Programming Language :: Python
    Programming Language :: Python :: 2
    Programming Language :: Python :: 2.7
    Programming Language :: Python :: 3
    Programming Language :: Python :: 3.5

[global]
setup-hooks =
    pbr.hooks.setup_hook

[files]
data_files =
    etc/nova =
        etc/nova/api-paste.ini
        etc/nova/rootwrap.conf
    etc/nova/rootwrap.d = etc/nova/rootwrap.d/*
packages =
    nova

[entry_points]
oslo.config.opts =
    nova.conf = nova.conf.opts:list_opts

oslo.config.opts.defaults =
    nova.conf = nova.common.config:set_middleware_defaults

oslo.policy.enforcer =
    nova = nova.policy:get_enforcer

oslo.policy.policies =
    # The sample policies will be ordered by entry point and then by list
    # returned from that entry point. If more control is desired split out each
    # list_rules method into a separate entry point rather than using the
    # aggregate method.
    nova = nova.policies:list_rules

nova.compute.monitors.cpu =
    virt_driver = nova.compute.monitors.cpu.virt_driver:Monitor

console_scripts =
    nova-api = nova.cmd.api:main
    nova-api-metadata = nova.cmd.api_metadata:main
    nova-api-os-compute = nova.cmd.api_os_compute:main
    nova-cells = nova.cmd.cells:main
    nova-compute = nova.cmd.compute:main
    nova-conductor = nova.cmd.conductor:main
    nova-console = nova.cmd.console:main
    nova-consoleauth = nova.cmd.consoleauth:main
    nova-dhcpbridge = nova.cmd.dhcpbridge:main
    nova-manage = nova.cmd.manage:main
    nova-network = nova.cmd.network:main
    nova-novncproxy = nova.cmd.novncproxy:main
    nova-policy = nova.cmd.policy_check:main
    nova-rootwrap = oslo_rootwrap.cmd:main
    nova-rootwrap-daemon = oslo_rootwrap.cmd:daemon
    nova-scheduler = nova.cmd.scheduler:main
    nova-serialproxy = nova.cmd.serialproxy:main
    nova-spicehtml5proxy = nova.cmd.spicehtml5proxy:main
    nova-status = nova.cmd.status:main
    nova-xvpvncproxy = nova.cmd.xvpvncproxy:main
wsgi_scripts =
    nova-placement-api = nova.api.openstack.placement.wsgi:init_application
    nova-api-wsgi = nova.api.openstack.compute.wsgi:init_application
    nova-metadata-wsgi = nova.api.metadata.wsgi:init_application

nova.ipv6_backend =
    rfc2462 = nova.ipv6.rfc2462
    account_identifier = nova.ipv6.account_identifier

nova.scheduler.host_manager =
    host_manager = nova.scheduler.host_manager:HostManager
    ironic_host_manager = nova.scheduler.ironic_host_manager:IronicHostManager

nova.scheduler.driver =
    filter_scheduler = nova.scheduler.filter_scheduler:FilterScheduler
    caching_scheduler = nova.scheduler.caching_scheduler:CachingScheduler
    chance_scheduler = nova.scheduler.chance:ChanceScheduler
    fake_scheduler = nova.tests.unit.scheduler.fakes:FakeScheduler

[build_sphinx]
all_files = 1
build-dir = doc/build
source-dir = doc/source
warning-is-error = 1

[build_apiguide]
all_files = 1
build-dir = api-guide/build
source-dir = api-guide/source

[egg_info]
tag_build =
tag_date = 0
tag_svn_revision = 0

[compile_catalog]
directory = nova/locale
domain = nova

[update_catalog]
domain = nova
output_dir = nova/locale
input_file = nova/locale/nova.pot

[extract_messages]
keywords = _ gettext ngettext l_ lazy_gettext
mapping_file = babel.cfg
output_file = nova/locale/nova.pot

[wheel]
universal = 1

[extras]
osprofiler =
  osprofiler>=1.4.0 # Apache-2.0
        接下来,只需要添加一个setup.py安装脚本即可。
import setuptools

# In python < 2.7.4, a lazy loading of package `pbr` will break
# setuptools if some other modules registered functions in `atexit`.
# solution from: http://bugs.python.org/issue15881#msg170215
try:
    import multiprocessing  # noqa
except ImportError:
    pass

setuptools.setup(
    setup_requires=['pbr>=2.0.0'],
    pbr=True)
        在这个脚本中,主要调用了setuptools.setup()方法,需要注意的是,在这个方法中,设置了pbr=True的参数,这就是说在使用setuptools进行安装时,会调用pbr.pbr()方法通过hook函数获取setup.cfg中的配置参数。
        最后执行如下命令就可以执行安装了:
python setup.py install
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值