定义选项¶
配置选项可以在命令行、环境或配置文件中设置。选项的优先级顺序为:命令行 > 环境 > 配置文件。
每个选项的模式使用 Opt 类或其子类定义,例如
from oslo_config import cfg
from oslo_config import types
PortType = types.Integer(1, 65535)
common_opts = [
cfg.StrOpt('bind_host',
default='0.0.0.0',
help='IP address to listen on.'),
cfg.Opt('bind_port',
type=PortType,
default=9292,
help='Port number to listen on.')
]
选项类型¶
选项可以通过 type 参数传递给 Opt 构造函数来拥有任意类型。 type 参数是一个可调用对象,它接收一个字符串并返回该特定类型的值,或者如果无法转换该值,则引发 ValueError 异常。
为了方便起见,oslo_config.cfg 中存在预定义的选项子类,它们将选项的 type 设置为下表所示:
类型 |
选项 |
|---|---|
对于 oslo_config.cfg.MultiOpt,item_type 参数定义了值的类型。为了方便起见,oslo_config.cfg.MultiStrOpt 是 MultiOpt,其 item_type 参数设置为 oslo_config.types.MultiString。
以下示例使用便捷类定义选项
enabled_apis_opt = cfg.ListOpt('enabled_apis',
default=['ec2', 'osapi_compute'],
help='List of APIs to enable by default.')
DEFAULT_EXTENSIONS = [
'nova.api.openstack.compute.contrib.standard_extensions'
]
osapi_compute_extension_opt = cfg.MultiStrOpt('osapi_compute_extension',
default=DEFAULT_EXTENSIONS)
注册选项¶
选项模式在运行时与配置管理器注册,但在引用选项之前。
class ExtensionManager:
enabled_apis_opt = cfg.ListOpt(...)
def __init__(self, conf):
self.conf = conf
self.conf.register_opt(enabled_apis_opt)
...
def _load_extensions(self):
for ext_factory in self.conf.osapi_compute_extension:
....
一种常见的用法模式是每个选项模式都定义在使用的模块或类中
opts = ...
def add_common_opts(conf):
conf.register_opts(opts)
def get_bind_host(conf):
return conf.bind_host
def get_bind_port(conf):
return conf.bind_port
选项可以选择性地通过命令行提供。此类选项必须在解析命令行之前与配置管理器注册(用于 –help 和 CLI 参数验证)。
请注意,为 CLI 使用注册的选项无需再次注册以从其他配置源(如文件)使用。CLI 选项可以从 CLI 或其他启用的配置源读取。
cli_opts = [
cfg.BoolOpt('verbose',
short='v',
default=False,
help='Print more verbose output.'),
cfg.BoolOpt('debug',
short='d',
default=False,
help='Print debugging output.'),
]
def add_common_opts(conf):
conf.register_cli_opts(cli_opts)
选项组¶
选项可以注册到组中
rabbit_group = cfg.OptGroup(name='rabbit',
title='RabbitMQ options')
rabbit_host_opt = cfg.StrOpt('host',
default='localhost',
help='IP/hostname to listen on.'),
rabbit_port_opt = cfg.PortOpt('port',
default=5672,
help='Port number to listen on.')
def register_rabbit_opts(conf):
conf.register_group(rabbit_group)
# options can be registered under a group in either of these ways:
conf.register_opt(rabbit_host_opt, group=rabbit_group)
conf.register_opt(rabbit_port_opt, group='rabbit')
如果除了组名之外不需要其他组属性,则无需显式注册该组,例如
def register_rabbit_opts(conf):
# The group will automatically be created, equivalent calling:
# conf.register_group(OptGroup(name='rabbit'))
conf.register_opt(rabbit_port_opt, group='rabbit')
如果未指定组,则选项属于配置文件的“DEFAULT”部分
glance-api.conf:
[DEFAULT]
bind_port = 9292
...
[rabbit]
host = localhost
port = 5672
use_ssl = False
userid = guest
password = guest
virtual_host = /
组中的命令行选项会自动以组名为前缀
--rabbit-host localhost --rabbit-port 9999
动态组¶
组可以由应用程序代码动态注册。这给示例生成器、发现机制和验证工具带来挑战,因为它们事先不知道所有组的名称。构造函数的 dynamic_group_owner 参数指定了另一个组中注册的选项的完整名称,该选项控制动态组的重复实例。此选项通常是 MultiStrOpt。
例如,Cinder 支持多个存储后端设备和服务。为了配置 Cinder 与多个后端通信,enabled_backends 选项设置为后端的名称列表。每个后端组都包含与该设备或服务通信的选项。
驱动组¶
组可以具有动态选项集,通常基于具有唯一要求的驱动程序。这在运行时有效,因为代码在注册选项之前使用它们,但它给示例生成器、发现机制和验证工具带来挑战,因为它们事先不知道组的正确选项。
为了解决此问题,可以使用 driver_option 参数命名组的驱动程序选项。每个驱动程序选项应定义其自己的发现入口点命名空间,以使用 "oslo.config.opts." 前缀后跟驱动程序选项名称来返回该驱动程序的选项集。
在上述 Cinder 的情况下,volume_backend_name 选项是组的静态定义的一部分,因此 driver_option 应设置为 "volume_backend_name"。插件应使用与使用 "oslo.config.opts" 注册的主插件相同的名称在 "oslo.config.opts.volume_backend_name" 下注册。Cinder 代码库中的驱动程序具有名为 "cinder" 的入口点注册。
特殊处理说明¶
可以声明选项为必需,以便如果用户未为该选项提供值,则会引发错误
opts = [
cfg.StrOpt('service_name', required=True),
cfg.StrOpt('image_id', required=True),
...
]
可以声明选项为机密,以便其值不会泄漏到日志文件中
opts = [
cfg.StrOpt('s3_store_access_key', secret=True),
cfg.StrOpt('s3_store_secret_key', secret=True),
...
]
字典选项¶
如果您需要最终用户指定键/值对的字典,则可以使用 DictOpt
opts = [
cfg.DictOpt('foo',
default={})
]
然后,最终用户可以在他们的配置文件中指定选项 foo,如下所示
[DEFAULT]
foo = k1:v1,k2:v2
高级选项¶
如果您需要将选项标记为高级选项,指示该选项通常不被大多数用户使用,并且可能对稳定性和/或性能产生重大影响,请使用
from oslo_config import cfg
opts = [
cfg.StrOpt('option1', default='default_value',
advanced=True, help='This is help '
'text.'),
cfg.PortOpt('option2', default='default_value',
help='This is help text.'),
]
CONF = cfg.CONF
CONF.register_opts(opts)
这将导致该选项被推送到命名空间的底部,并在示例文件中标记为高级选项,并附带有关可能影响的说明
[DEFAULT]
...
# This is help text. (string value)
# option2 = default_value
...
<pushed to bottom of section>
...
# This is help text. (string value)
# Advanced Option: intended for advanced users and not used
# by the majority of users, and might have a significant
# effect on stability and/or performance.
# option1 = default_value